CUBE,ROLLUP 和 GROUPING

来源:https://www.cnblogs.com/outmanxiaozhou/archive/2018/12/12/10107304.html
-Advertisement-
Play Games

1.用 CUBE 彙總數據 CUBE 運算符生成的結果集是多維數據集。多維數據集是事實數據的擴展,事實數據即記錄個別事件的數據。擴展建立在用戶打算分析的列上。這些列被稱為維。多維數據集是一個結果集,其中包含了各維度的所有可能組合的交叉表格。 CUBE 運算符在 SELECT 語句的 GROUP BY ...


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                       

我們先來準備測試表和數據

複製代碼
IF object_id(N'Inventory',N'U') IS NOT NULL
    DROP TABLE Inventory

CREATE TABLE Inventory
(
Item varchar(255),
Color varchar(255),
Quantity decimal(18,8)
)

--插入數據
INSERT INTO Inventory
SELECT 'Chair','Blue',101.00
UNION ALL
SELECT 'Chair', 'Red',210.00
UNION ALL
SELECT 'Table','Blue',124.00
UNION ALL
SELECT 'Table','Red',223.00
複製代碼

 

下列查詢返回的結果集中,將包含 ItemColor 的所有可能組合的 Quantity 小計:

SELECT Item, Color, SUM(Quantity) AS QtySum

FROM Inventory

GROUP 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                    

這一行報告了多維數據集的總計。ItemColor 維度的值都是 NULL,表示兩個維度中的所有值都彙總在該行中。

(null)               Blue                 225.00                    

(null)               Red                  433.00                    

這兩行報告了 Color 維度的小計。兩行中的 Item 維度值都是 NULL,表示聚合數據來自 Item 維度為任意值的行。

使用 GROUPING 區分空值

CUBE 操作所生成的空值帶來一個問題:如何區分 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 QtySum

FROM Inventory

GROUP BY Item, Color WITH CUBE
複製代碼

 

--小小的解釋一下,如果GROUPING(Item)如果是有值,那麼GROUPING(Item)=0,那麼這一整段都不會執行,那麼程式將繼續往下走,來到SUM(Quantity) AS QtySum這裡,所以查出的結果也是有值的,所以值並不是ALL,ALL是當為Null的時候,也就是某一欄位全部SUM的時候,明白了嗎?這裡我也花了一點時間才理解透,其實都很簡單的--

多維數據集

CUBE 運算符可用於生成 n 維的多維數據集,即具有任意數目維度的多維數據集。只有一個維度的多維數據集可用於生成合計,例如:

複製代碼
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'

            ELSE ISNULL(Item, 'UNKNOWN')

       END AS Item,

       SUM(Quantity) AS QtySum

FROM Inventory

GROUP BY Item WITH CUBE

GO
複製代碼

 

此 SELECT 語句返回的結果集既顯示了 Item 中每個值的小計,也顯示了 Item 中所有值的總計:

Item                 QtySum                    

-------------------- --------------------------

Chair                311.00                    

Table                347.00                    

ALL                  658.00                    

包含帶有許多維度的 CUBE 的 SELECT 語句可能生成很大的結果集,因為這些語句會為所有維度中值的所有組合生成行。這些大結果集包含的數據可能過多而不易於閱讀和理解。這個問題有一種解決辦法是將 SELECT 語句放在視圖中:

複製代碼
CREATE VIEW InvCube AS

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 QtySum

FROM Inventory

GROUP BY Item, Color WITH CUBE
複製代碼

 

然後即可用該視圖來只查詢您感興趣的維度值:

複製代碼
SELECT *

FROM InvCube

WHERE Item = 'Chair'

  AND Color = 'ALL'
複製代碼

 

Item                 Color                QtySum                    

-------------------- -------------------- --------------------------

Chair                ALL                  311.00                    

 

(1 row(s) affected)

2.用 ROLLUP 彙總數據

在生成包含小計和合計的報表時,ROLLUP 運算符很有用。ROLLUP 運算符生成的結果集類似於 CUBE 運算符所生成的結果集。

CUBE 和 ROLLUP 之間的區別在於:

  •     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 QtySum

FROM Inventory

GROUP BY Item, Color WITH ROLLUP
複製代碼

 

Item                 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 操作為 ItemColor 中值的可能組合生成行。例如,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 具有下列優點:

  • ROLLUP 返回單個結果集;COMPUTE BY 返回多個結果集,而多個結果集會增加應用程式代碼的複雜性。
  • ROLLUP 可以在伺服器游標中使用;COMPUTE BY 不可以。
  • 有時,查詢優化器為 ROLLUP 生成的執行計劃比為 COMPUTE BY 生成的更為高效。

3.GROUPING函數

是一個聚合函數,它產生一個附加的列,當用 CUBE 或 ROLLUP 運算符添加行時,附加的列輸出值為1,當所添加的行不是由 CUBE 或 ROLLUP 產生時,附加列值為0

僅在與包含 CUBE 或 ROLLUP 運算符的 GROUP BY 子句相聯繫的選擇列表中才允許分組。

語法

GROUPING ( column_name )

參數

column_name

是 GROUP BY 子句中用於檢查 CUBE 或 ROLLUP 空值的列。

返回類型

int

註釋

分組用於區分由 CUBE 和 ROLLUP 返回的空值和標準的空值。作為CUBE 或 ROLLUP 操作結果返回的 NULL 是 NULL 的特殊應用。它在結果集內作為列的占位符,意思是"全體"

示例

下麵的示例將 royalty 的數值分組,並聚合 advance 的數值。GROUPING 函數應用於 royalty 列。

複製代碼
USE pubs

SELECT royalty, SUM(advance) 'total advance',

   GROUPING(royalty) 'grp'

   FROM titles

   GROUP BY royalty WITH ROLLUP
複製代碼

 

結果集在 royalty 下顯示兩個空值。第一個 NULL 代表從表中這一列得到的空值組。第二個 NULL 在 ROLLUP 操作所添加的彙總行中。彙總行顯示的是所有 royalty 組的 advance 合計數值,並且在 grp 列中用 1 標識。

下麵是結果集:

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 

為了更清晰的搞明白,舉個慄子看下rollup 、cube 不同

創建表:

CREATE TABLE DEPART   

(部門 char(10),員工 char(6),工資 int)

INSERT INTO DEPART SELECT 'A','ZHANG',100   

INSERT INTO DEPART SELECT 'A','LI',200    

INSERT INTO DEPART SELECT 'A','WANG',300    

INSERT INTO DEPART SELECT 'A','ZHAO',400    

INSERT INTO DEPART SELECT 'A','DUAN',500    

INSERT INTO DEPART SELECT 'B','DUAN',600    

INSERT INTO DEPART SELECT 'B','DUAN',700

部門         員工         工資

A             ZHANG     100   

A             LI             200    

A             WANG      300    

A             ZHAO      400    

A             DUAN      500    

B             DUAN      600    

B             DUAN      700

(1)GROUP BY 

SELECT 部門,員工,SUM(工資)AS TOTAL   

FROM DEPART    

GROUP BY 部門,員工

結果:

A             DUAN      500   

B             DUAN      1300    

A             LI        200    

A             WANG      300    

A             ZHANG     100    

A             ZHAO      400

(2)ROLLUP

SELECT 部門,員工,SUM(工資)AS TOTAL   

FROM DEPART    

GROUP BY  部門,員工  WITH ROLLUP

結果:

A             DUAN       500   

A             LI             200    

A             WANG      300    

A             ZHANG     100    

A             ZHAO       400    

A             NULL        1500    

B             DUAN       1300    

B             NULL       1300    

NULL       NULL        2800

ROLLUP結果集中多了三條彙總信息:即部門A的合計,部門B的合計以及總合計。其中將部門B中的DUAN合計。

等價於下列SQL語句

SELECT 部門,員工,SUM(工資)AS TOTAL   

FROM DEPART    

GROUP BY 部門,員工    

union    

SELECT 部門,'NULL',SUM(工資)AS TOTAL    

FROM DEPART    

GROUP BY  部門    

union    

SELECT 'NULL','NULL',SUM(工資)AS TOTAL    

FROM DEPART

結果:

A             DUAN      500   

A             LI           200    

A             NULL      1500    

A             WANG      300    

A             ZHANG     100    

A             ZHAO       400    

B             DUAN      1300    

B             NULL       1300    

NULL       NULL        2800

(3)CUBE

SELECT 部門,員工,SUM(工資)AS TOTAL   

FROM DEPART    

GROUP BY 部門,員工 WITH CUBE

結果:

A             DUAN      500   

A             LI           200    

A             WANG      300    

A             ZHANG     100    

A             ZHAO      400    

A             NULL      1500    

B             DUAN      1300    

B             NULL      1300    

NULL    NULL         2800    

NULL    DUAN        1800    

NULL    LI               200    

NULL    WANG       300    

NULL    ZHANG       100    

NULL    ZHAO         400

CUBE的結果集是在 ROLLUP結果集的基礎上多了5行,這5行相當於在ROLLUP結果集上在union 上以員工 (即CUBE)為 GROUP BY的結果。

等價於下列的SQL語句:

SELECT 部門,員工,SUM(工資)AS TOTAL   

FROM DEPART    

GROUP BY  部門,員工  WITH ROLLUP

union

SELECT 'NULL',員工,SUM(工資)AS TOTAL   

FROM DEPART    

GROUP BY 員工

結果:

A             DUAN      500   

A             LI           200    

A             WANG      300    

A             ZHANG     100    

A             ZHAO      400    

A             NULL      1500    

B             DUAN      1300    

B             NULL      1300    

NULL    NULL         2800    

NULL    DUAN        1800    

NULL    LI               200    

NULL    WANG       300    

NULL    ZHANG       100    

NULL    ZHAO         400


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 嚴謹轉載--否則追究法律責任 作者 王加鴻 bug 1 解決方案 將這兩個路徑下的文件清空即可 ↑ 解決方案: 暫無(如無法連接,會自動創建連接,但可能長久後會造成連接過多) bug 3 解決方案:初步分析,是埋點數據產生的json格式解析出問題了 後來查看源代碼在org.apache.flume. ...
  • 樹 樹,大家都見過,以這種形式的數據關係,就是樹。下麵看一張圖,瞭解什麼是根節點(樹幹)、節點或分叉、葉(葉節點) connect by 級聯查詢 connect by可以用於級聯查詢,常用於對具有樹狀結構的記錄查詢某一節點的所有子孫節點或所有祖輩節點。 來看一個示例,現假設我們擁有一個菜單表t_m ...
  • 一. Redis的介紹 Redis 是一個Key-Value存儲的系統;它支持存儲的value類型有string(字元串),list(列表),set(集合),zset(有序集合);為了保證效率;數據都緩存在記憶體中;它也周期性將記憶體數據寫入磁碟或者把讀寫操作寫入記錄文件。Redis使用單線程模型;還有 ...
  • update B b set b.value=(select max(a.value) from A a where b.key=a.key) where exists(select 1 from A c where b.key=c.key) UPDATE A a,(select a.`key`,b... ...
  • 1 MYSQL常用命令 2 1.導出整個資料庫 3 mysqldump -u 用戶名 -p –default-character-set=latin1 資料庫名 > 導出的文件名(資料庫預設編碼是latin1) 4 mysqldump -u wcnc -p smgp_apps_wcnc > wcnc ...
  • redis資料庫的基本類型分析: 1、string 最基本的數據類型。只存貯一個值,key-value,最大值存儲512M. 創建命令:hmset 讀取命令:hget 2、hash 集合,存儲為一個集合。適合一個對象的存儲。創建命令:hmset ,field1 field2...,其中field1這 ...
  • 因為很多存儲過程都會共用一段sql語句,所以我把共用的sql封裝成一個自定義函數 AddCapital(); 然後通過存儲過程調用,創建存儲過程會報錯1415,Not allowed to return a result set from a function(不允許從函數返回結果集);因為存儲過程 ...
  • 本文由雲+社區發表 一、 問題是這樣來的 ​ 2018年某個周末,接到連續資料庫的告警,告警信息如下: 二、 苦逼的探索過程 1、總體的思路 看到too many connection的報錯信息,基本上可以把問題定位在: (1)機器負載飆升,導致SQL執行效率下降,導致連接推積 (2)業務訪問量突增 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...