在 Web 應用程式開發中,分類數據統計是極為常見的需求。以電子商務網站為例,我們經常需要按商品類別統計銷售金額與銷售數量。在 ASP.NET 環境下,如何同時在 DataGrid 中顯示明細資料,又能依類別彙總統計?雖然方法眾多,但本文要介紹一個常被忽略卻極具效率的技巧——善用 MS SQL Server 的 ROLLUP 子句。
ROLLUP 子句需搭配 GROUP BY 使用,當我們既需要分類求和,又需要取得所有分類的總和時,它能發揮極大效用。以 Northwind 資料庫為例,若要查詢各類別下產品的總價格與庫存量,基本查詢如下:
SELECT
CategoryName,
SUM(UnitPrice) as UnitPrice,
SUM(UnitsinStock) as UnitsinStock
FROM Products
INNER JOIN Categories On
Products.CategoryID = Categories.CategoryID
GROUP BY CategoryName
執行結果僅呈現各類別的彙總資料。但若需求升級:既要列出分類下的每個產品明細,又要同時顯示各分類小計與整體總計,ROLLUP 便大顯身手。我們期望的效果如下圖所示:
圖中黃色區域即為關鍵:例如 Meat/Poultry 類別的小計列,顯示該分類所有產品的總價格與總數量;最底部一行則為所有分類的總計。ROLLUP 的本質就是在直向上,同時對分類求和並求所有分類的總和。
使用 ROLLUP 時需注意:統計列會產生 NULL 值。例如分類小計列的 ProductName 會是 NULL,總計列的 CategoryName 也會是 NULL。若直接呈現給使用者會造成困擾,可透過 GROUPING() 函數搭配 CASE WHEN 進行替換:
SELECT
CASE
WHEN (GROUPING(CategoryName)=1) THEN '總計'
ELSE CategoryName
END AS CategoryName,
CASE
WHEN (GROUPING(ProductName)=1) THEN '小計'
ELSE ProductName
END AS ProductName,
SUM(UnitPrice) as UnitPrice,
SUM(UnitsinStock) as UnitsInStock
FROM Products
INNER JOIN Categories On
Products.CategoryID = Categories.CategoryID
GROUP BY CategoryName, ProductName WITH ROLLUP
此語句中,GROUPING() 回傳 1 表示該欄位為彙總產生的 NULL,我們即可自訂顯示文字(如「小計」、「總計」),使報表更易讀、更專業。
ROLLUP 是 SQL Server 內建的高效彙總工具,能一次查詢完成明細、分類小計與整體總計的顯示,省去應用層二次運算的麻煩。搭配 GROUPING() 處理 NULL 值,即可產出可直接呈現給使用者的專業統計報表。