查看SQL Server的幫助才發(fā)現,厲害啊,原來還有這么厲害的東西,不由的想起以前做水晶報表的時候,原來在SQL Server中就可以實現這樣的功能.
第一次看到這樣的SQL語句,看不懂,其中用到了下面的不常用的
聚集函數:GROUPING
用于匯總數據用的運算符: ROLLUP
SELECT
CASE GROUPING(o.customerid) WHEN 0 THEN o.customerid ELSE ‘(Total)’ END
AS AllCustomersSummary,
CASE GROUPING(od.orderid) WHEN 0 THEN od.orderid ELSE -1 END
AS IndividualCustomerSummary,
SUM(od.quantity*od.unitprice) AS price
FROM Orders o, [Order Details] od
WHERE Year(o.orderdate) = 1998 AND od.orderid=o.orderid
GROUP BY o.customerid, od.orderid WITH ROLLUP
ORDER BY AllCustomersSummary
查看SQL Server的幫助才發(fā)現,厲害啊,原來還有這么厲害的東西,不由的想起以前做水晶報表的時候,原來在SQL Server中就可以實現這樣的功能.
1.用 CUBE 匯總數據
CUBE 運算符生成的結果集是多維數據集。多維數據集是事實數據的擴展,事實數據即記錄個別事件的數據。擴展建立在用戶打算分析的列上。這些列被稱為維。多維數據集是一個結果集,其中包含了各維度的所有可能組合的交叉表格。
CUBE 運算符在 SELECT 語句的 GROUP BY 子句中指定。該語句的選擇列表應包含維度列和聚合函數表達式。GROUP BY 應指定維度列和關鍵字 WITH CUBE。結果集將包含維度列中各值的所有可能組合,以及與這些維度值組合相匹配的基礎行中的聚合值。
例如,一個簡單的表 Inventory 中包含:
Item Color Quantity -------------------- -------------------- -------------------------- Table Blue 124 Table Red 223 Chair Blue 101 Chair Red 210
下列查詢返回的結果集中,將包含 Item 和 Color 的所有可能組合的 Quantity 小計:
SELECT Item, Color, SUM(Quantity) AS QtySumFROM InventoryGROUP BY Item, Color WITH CUBE
下面是結果集:
Item Color QtySum -------------------- -------------------- -------------------------- Chair Blue 101.00 Chair Red 210.00 Chair (null) 311.00 Table Blue 124.00 Table Red 223.00 Table (null) 347.00 (null) (null) 658.00 (null) Blue 225.00 (null) Red 433.00
我們著重考查下列各行:
Chair (null) 311.00
這一行報告了 Item 維度中值為 Chair 的所有行的小計。對 Color 維度返回了 NULL 值,表示該行所報告的聚合包括 Color 維度為任意值的行。
Table (null) 347.00
這一行類似,但報告的是 Item 維度中值為 Table 的所有行的小計。
(null) (null) 658.00
這一行報告了多維數據集的總計。Item 和 Color 維度的值都是 NULL,表示兩個維度中的所有值都匯總在該行中。
(null) Blue 225.00 (null) Red 433.00
這兩行報告了 Color 維度的小計。兩行中的 Item 維度值都是 NULL,表示聚合數據來自 Item 維度為任意值的行。
使用 GROUPING 區(qū)分空值
CUBE 操作所生成的空值帶來一個問題:如何區(qū)分 CUBE 操作所生成的 NULL 值和從實際數據中返回的 NULL 值?這個問題可用 GROUPING 函數解決。如果列中的值來自事實數據,則 GROUPING 函數返回 0;如果列中的值是 CUBE 操作所生成的 NULL,則返回 1。在 CUBE 操作中,所生成的 NULL 代表全體值。可將 SELECT 語句寫成使用 GROUPING 函數將所生成的 NULL 替換為字符串 ALL。因為事實數據中的 NULL 表明數據值未知,所以 SELECT 語句還可譯碼為返回字符串 UNKNOWN 替代來自事實數據的 NULL。例如:
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL' ELSE ISNULL(Item, 'UNKNOWN') END AS Item, CASE WHEN (GROUPING(Color) = 1) THEN 'ALL' ELSE ISNULL(Color, 'UNKNOWN') END AS Color, SUM(Quantity) AS QtySumFROM InventoryGROUP BY Item, Color WITH CUBE
多維數據集
CUBE 運算符可用于生成 n 維的多維數據集,即具有任意數目維度的多維數據集。只有一個維度的多維數據集可用于生成合計,例如:
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL' ELSE ISNULL(Item, 'UNKNOWN') END AS Item, SUM(Quantity) AS QtySumFROM InventoryGROUP BY Item WITH CUBEGO
此 SELECT 語句返回的結果集既顯示了 Item 中每個值的小計,也顯示了 Item 中所有值的總計:
Item QtySum -------------------- -------------------------- Chair 311.00 Table 347.00 ALL 658.00
包含帶有許多維度的 CUBE 的 SELECT 語句可能生成很大的結果集,因為這些語句會為所有維度中值的所有組合生成行。這些大結果集包含的數據可能過多而不易于閱讀和理解。這個問題有一種解決辦法是將 SELECT 語句放在視圖中:
CREATE VIEW InvCube ASSELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL' ELSE ISNULL(Item, 'UNKNOWN') END AS Item, CASE WHEN (GROUPING(Color) = 1) THEN 'ALL' ELSE ISNULL(Color, 'UNKNOWN') END AS Color, SUM(Quantity) AS QtySumFROM InventoryGROUP BY Item, Color WITH CUBE
然后即可用該視圖來只查詢您感興趣的維度值:
SELECT *FROM InvCubeWHERE Item = 'Chair' AND Color = 'ALL'Item Color QtySum -------------------- -------------------- -------------------------- Chair ALL 311.00 (1 row(s) affected)
2.用 ROLLUP 匯總數據
在生成包含小計和合計的報表時,ROLLUP 運算符很有用。ROLLUP 運算符生成的結果集類似于 CUBE 運算符所生成的結果集。有關更多信息.
CUBE 和 ROLLUP 之間的區(qū)別在于:
- CUBE 生成的結果集顯示了所選列中值的所有組合的聚合。
- ROLLUP 生成的結果集顯示了所選列中值的某一層次結構的聚合。
例如,簡單表 Inventory 中包含:
Item Color Quantity -------------------- -------------------- -------------------------- Table Blue 124 Table Red 223 Chair Blue 101 Chair Red 210
下列查詢將生成小計報表:
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL' ELSE ISNULL(Item, 'UNKNOWN') END AS Item, CASE WHEN (GROUPING(Color) = 1) THEN 'ALL' ELSE ISNULL(Color, 'UNKNOWN') END AS Color, SUM(Quantity) AS QtySumFROM InventoryGROUP BY Item, Color WITH ROLLUPItem Color QtySum -------------------- -------------------- -------------------------- Chair Blue 101.00 Chair Red 210.00 Chair ALL 311.00 Table Blue 124.00 Table Red 223.00 Table ALL 347.00 ALL ALL 658.00 (7 row(s) affected)
如果查詢中的 ROLLUP 關鍵字更改為 CUBE,那么 CUBE 結果集與上述結果相同,只是在結果集的末尾還會返回下列兩行:
ALL Blue 225.00 ALL Red 433.00
CUBE 操作為 Item 和 Color 中值的可能組合生成行。例如,CUBE 不僅報告與 Item 值 Chair 相組合的 Color 值的所有可能組合(Red、Blue 和 Red + Blue),而且報告與 Color 值 Red 相組合的 Item 值的所有可能組合(Chair、Table 和 Chair + Table)。
對于 GROUP BY 子句中右邊的列中的每個值,ROLLUP 操作并不報告左邊一列(或左邊各列)中值的所有可能組合。例如,ROLLUP 并不對每個 Color 值報告 Item 值的所有可能組合。
ROLLUP 操作的結果集具有類似于 COMPUTE BY 所返回結果集的功能;然而,ROLLUP 具有下列優(yōu)點:
- ROLLUP 返回單個結果集;COMPUTE BY 返回多個結果集,而多個結果集會增加應用程序代碼的復雜性。
- ROLLUP 可以在服務器游標中使用;COMPUTE BY 不可以。
- 有時,查詢優(yōu)化器為 ROLLUP 生成的執(zhí)行計劃比為 COMPUTE BY 生成的更為高效。
3.GROUPING
是一個聚合函數,它產生一個附加的列,當用 CUBE 或 ROLLUP 運算符添加行時,附加的列輸出值為1,當所添加的行不是由 CUBE 或 ROLLUP 產生時,附加列值為0。
僅在與包含 CUBE 或 ROLLUP 運算符的 GROUP BY 子句相聯系的選擇列表中才允許分組。
語法
GROUPING <b>(</b> <i>column_name </i><b>)</b>
參數
column_name
是 GROUP BY 子句中用于檢查 CUBE 或 ROLLUP 空值的列。
返回類型
int
注釋
分組用于區(qū)分由 CUBE 和 ROLLUP 返回的空值和標準的空值。作為CUBE 或 ROLLUP 操作結果返回的 NULL 是 NULL 的特殊應用。它在結果集內作為列的占位符,意思是”全體”。
示例
下面的示例將 royalty 的數值分組,并聚合 advance 的數值。GROUPING 函數應用于 royalty 列。
<CODE>USE pubsSELECT royalty, SUM(advance) 'total advance', GROUPING(royalty) 'grp'</CODE> <CODE>FROM titles GROUP BY royalty WITH ROLLUP</CODE>
結果集在 royalty 下顯示兩個空值。第一個 NULL 代表從表中這一列得到的空值組。第二個 NULL 在 ROLLUP 操作所添加的匯總行中。匯總行顯示的是所有 royalty 組的 advance 合計數值,并且在 grp 列中用 1 標識。
下面是結果集:
<CODE>royalty total advance grp --------- --------------------- ---NULL NULL 0 10 57000.0000 0 12 2275.0000 0 14 4000.0000 0 16 7000.0000 0 24 25125.0000 0 NULL 95400.0000 1 </CODE>
3.GROUPING
是一個聚合函數,它產生一個附加的列,當用 CUBE 或 ROLLUP 運算符添加行時,附加的列輸出值為1,當所添加的行不是由 CUBE 或 ROLLUP 產生時,附加列值為0。
僅在與包含 CUBE 或 ROLLUP 運算符的 GROUP BY 子句相聯系的選擇列表中才允許分組。
語法
GROUPING <b>(</b> <i>column_name </i><b>)</b>
參數
column_name
是 GROUP BY 子句中用于檢查 CUBE 或 ROLLUP 空值的列。
返回類型
int
注釋
分組用于區(qū)分由 CUBE 和 ROLLUP 返回的空值和標準的空值。作為CUBE 或 ROLLUP 操作結果返回的 NULL 是 NULL 的特殊應用。它在結果集內作為列的占位符,意思是”全體”。
示例
下面的示例將 royalty 的數值分組,并聚合 advance 的數值。GROUPING 函數應用于 royalty 列。
<CODE>USE pubsSELECT royalty, SUM(advance) 'total advance', GROUPING(royalty) 'grp'</CODE> <CODE>FROM titles GROUP BY royalty WITH ROLLUP</CODE>
結果集在 royalty 下顯示兩個空值。第一個 NULL 代表從表中這一列得到的空值組。第二個 NULL 在 ROLLUP 操作所添加的匯總行中。匯總行顯示的是所有 royalty 組的 advance 合計數值,并且在 grp 列中用 1 標識。
下面是結果集:
<CODE>royalty total advance grp --------- --------------------- ---NULL NULL 0 10 57000.0000 0 12 2275.0000 0 14 4000.0000 0 16 7000.0000 0 24 25125.0000 0 NULL 95400.0000 1 </CODE>
3.GROUPING
是一個聚合函數,它產生一個附加的列,當用 CUBE 或 ROLLUP 運算符添加行時,附加的列輸出值為1,當所添加的行不是由 CUBE 或 ROLLUP 產生時,附加列值為0。
僅在與包含 CUBE 或 ROLLUP 運算符的 GROUP BY 子句相聯系的選擇列表中才允許分組。
語法
GROUPING <b>(</b> <i>column_name </i><b>)</b>
參數
column_name
是 GROUP BY 子句中用于檢查 CUBE 或 ROLLUP 空值的列。
返回類型
int
注釋
分組用于區(qū)分由 CUBE 和 ROLLUP 返回的空值和標準的空值。作為CUBE 或 ROLLUP 操作結果返回的 NULL 是 NULL 的特殊應用。它在結果集內作為列的占位符,意思是”全體”。
示例
下面的示例將 royalty 的數值分組,并聚合 advance 的數值。GROUPING 函數應用于 royalty 列。
<CODE>USE pubsSELECT royalty, SUM(advance) 'total advance', GROUPING(royalty) 'grp'</CODE> <CODE>FROM titles GROUP BY royalty WITH ROLLUP</CODE>
結果集在 royalty 下顯示兩個空值。第一個 NULL 代表從表中這一列得到的空值組。第二個 NULL 在 ROLLUP 操作所添加的匯總行中。匯總行顯示的是所有 royalty 組的 advance 合計數值,并且在 grp 列中用 1 標識。
下面是結果集:
<CODE>royalty total advance grp --------- --------------------- ---NULL NULL 0 10 57000.0000 0 12 2275.0000 0 14 4000.0000 0 16 7000.0000 0 24 25125.0000 0 NULL 95400.0000 1 </CODE>
對GROUPING,ROLLUP,CUBE的介紹來自SQL Server2000中文版的幫助.