作者: Tomex Ou
版本歷史:
2008/08/18 PM 11:52:17 厭煩Table資料loop土法計算方式的研究心得。
研究動機
要從Remote資料庫取得資料製成一份統計分析報表人人會寫,但寫得好且有效率的卻不多。尤其在資料庫規劃可能不佳的情況下,您若硬寫硬算,雖可解決問題卻會失去運算效率,資料量一大,報表要跑好久。尤其資歷的Programmer可能亂下一大串只顧自己卻罔顧他人死活的Dirty SQL,最後資料庫主機老是高承載,裏頭的系統程式像骨牌般倒下。
嚴謹公司(如銀行)的DBA會替Programmer所下的SQL檢查把關,通常不會允許具有大量複雜/迴圈計算的SQL Script執行,這時候Programmer只能初步過濾資料後傳回Client端去處理。失去基本SQL過濾運算資料的幫忙,Programmer會苦惱著如何在DataTable物件中如何過濾及GROUP BY群組分類的計算工作,因為DataTable並沒有「直覺地」提供這些群組彙集函式。
資深的Programmer就利用迴圈及自己多年經驗的演算法湊合著用,程式開始出現一大堆code,造成日後維護上的不易閱讀性。本篇文章主要就要探討,如何透過DataTable來實作資料群組彙集操作(Group Aggregation)的相關方式。
問題探討
以下圖Table為例,你可以透過DataTable.Select(express, sort)或DataView.Filter來取得子群組資料,但在這之前,你得對ChildKey欄位作Group By動作以取得Distinct唯一值,多數人會用loop集合來實作唯一性的檢查,再透過sub資料集合的擷取即可。

這僅是一個欄位Group By的統計觀點,多遇上幾個,程式冗碼就會開始爆增。數字上的加總/平均值都還簡單實作,遇到max/min等判斷就麻煩了,偶爾又要加個分析欄位下去,甚至可能推翻既有的架構。它證明了用土法煉鋼的方式寫報表,日子肯定會過得挺無趣的。
解法示範
比較好的作法是將需要group by的key欄位分離成一個DataTable,透過Relation的關係來操作Child資料,即可減去不斷地loop之苦。首先,我們透過下面的方式取得一個Distinct ParentTable內容:
其實不需要單獨把Key欄位拉出去唯一/排序,畢竟最終它還是要塞回DataTable作操作,利用上面的語法直接建立ParentTable即可。
最重要我們建立ParentTable的好處在於能利用Relation:
利用
Column.Expression來作Child資料的彙總計算。
善用Relation,你可以方便地擷取ChildTable的資料並計算,最後取得報表所需的累計暫存資料:

文章結論
由本文可知,重點在於DataTable的Expression格式字串,它能幫你簡化欄位上統計計算的麻煩。