Pivot Table 是樞紐分析表的意思,如下一個普通的資料集:
當按日期作為x軸,客戶ID作為y軸,利潤作為資料(SUM),轉換為樞紐分析表後呈現為:
其中的利潤資料將被合計,而無資料的位置被“-”字元代替。
那麼實現一個這樣的資料展現模式,方法有多種,在排開專用工具軟體之外,一般存在三種方式:
一、使用支援多維展示資料的網格控制項或報表控制項。
二、編寫SQL來實現。
三、通過編程開發自訂的函數將資料做轉換。
這三種方式,它們各有優缺點:
一、使用網格控制項則必須購買三方廠商開發的組件,而報表工具/組件則只能在特定的情境應用並展示資料。
二、SQL方式只是相對靈活,但如果x軸是動態,如年月日,或者是某個項目(沒有參照表),就需要代碼來拼接SQL,不能寫死,但這種方式的功能卻很強大,像彙總函式之類的,通常在報表中,就是先寫SQL儘可能的接近於最終格式,再使用報表工具最佳化或處理資料格式。
三、編程方式,優點是可以很靈活的公開介面和實現需求,缺點是如果要做的完善,工作強度相對比較大(技術基礎,開發時間,可用性,穩定性,效能)。
通常要滿足一、二兩點,是相對容易的,而第三點編程方式相對來說,可利用的資源不多;因為最合適的還是自己根據項目需求而定製開發的。
那麼針對第三點編程方式的思路做以下講解:
一、樞紐分析表的x軸和y軸的
這裡的x軸和y軸表示為
x軸的列提取:
構造新記憶體表;
排除X軸欄位和資料欄位,將其他欄位產生Y軸列;
foreach (資料列 列 in 原始表.列集合)
if (列名稱!=X軸欄位 && 列名稱!=資料欄位)
新記憶體表.增加列(列);
從資料中找出欄欄位值產生列;
foreach (資料行 行 in 原始表.行集合)
if (行[X軸欄位]不存在)
新記憶體表.增加列(行[X軸欄位]);
y軸的資料分組過濾和資料列填入:
//遍曆資料,填寫資料
foreach (資料行 行 in 原始表.行集合)
{
//比較分組列資料,保持唯一
string 比較值一 = 行[Y軸欄位];
bool 存在相同 = 新記憶體表.行集合.尋找(比較值一);
//無相同的,則增加到分組資料集合
if (!存在相同)
{
構造記憶體表新行;
//複製分組列資料
新行[Y軸列] = 行[Y軸列] ;
}
//尋找資料列的資料
foreach (資料行 尋找行 in 新記憶體表.行集合)
{
string 比較值二 = 尋找行[Y軸欄位];
//如果和分組資料相同,則增加到對應的資料儲存格
if (比較值一==比較值二)
尋找行[行[X軸列] + ""] = 行[資料列];
}
}
二、資料列的彙總實現
彙總函式運算,思路是在填寫x軸的資料欄位資料的時候,將它的原始值登記到一個運算表內,作為儲存;其中y軸資料作為key,x軸資料作為它子集的key,再在其中存放一個有序的List,其中存放的則是每行的未經處理資料值。
//彙總函式運算表
Dictionary<y軸列行資料, Dictionary<x軸列, List<x軸列資料集合>>> expressRows;
此圖比較大,請配合下面的偽碼
//拿到了集合,後計算彙總函式和填充空文本
foreach (資料行 尋找行 in 新記憶體表.行集合)
{
string 比較值二 =尋找行[Y軸欄位];
//尋找需要計算的儲存格
foreach (string x軸列 in x軸列集合)
{
decimal avg, sum, max, min;
avg = sum = max = min = 0;
//排除空
if (彙總函式運算表.ContainsKey(比較值二) && 彙總函式運算表[比較值二].ContainsKey(x軸列))
{
//產生彙總結果
foreach (decimal d in 彙總函式運算表[比較值二][x軸列])
{
avg += d;
sum += d;
if (d > max) max = d;
if (min == 0) min = d;
if (min > d) min = d;
}
//平均特殊處理
if (彙總函式運算表[比較值二][x軸列].Count > 0)
avg = avg / 彙總函式運算表[比較值二][x軸列].Count;
else
avg = 0;
//分配彙總結果
if (dataExpression != PivotDataExpression.None)
{
switch (dataExpression)
{
case PivotDataExpression.Avg:
尋找行[x軸列] = avg;
break;
case PivotDataExpression.Max:
尋找行[x軸列]= max;
break;
case PivotDataExpression.Sum:
尋找行[x軸列]= sum;
break;
case PivotDataExpression.Min:
尋找行[x軸列]= min;
break;
case PivotDataExpression.Count:
尋找行[x軸列]= 彙總函式運算表[比較值二][x軸列].Count;
break;
}
}
}
//填充空文本
if (尋找行.IsNull(x軸列))
尋找行[x軸列]= 空文本;
}
}
三、x軸和y軸的合計或公式套用的靈活實現
待續……
四、x軸和y軸的合計列實現
待續……