SQL Server 之 GROUP BY、GROUPING SETS、ROLLUP、CUBE

1.建立表 Staffhtml

CREATE TABLE [dbo].[Staff](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NULL,
    [Sex] [varchar](50) NULL,
    [Department] [varchar](50) NULL,
    [Money] [int] NULL,
    [CreateDate] [datetime] NULL
) ON [PRIMARY]

GO

 

2.爲Staff表填充數據函數

INSERT INTO [dbo].[Staff]([Name],[Sex],[Department],[Money],[CreateDate])
SELECT 'Name1','','技術部',3000,'2011-11-12'
UNION ALL
SELECT 'Name2','','工程部',4000,'2013-11-12'
UNION ALL
SELECT 'Name3','','工程部',3000,'2013-11-12'
UNION ALL
SELECT 'Name4','','技術部',5000,'2012-11-12'
UNION ALL
SELECT 'Name5','','技術部',6000,'2011-11-12'
UNION ALL
SELECT 'Name6','','技術部',4000,'2013-11-12'
UNION ALL
SELECT 'Name7','','技術部',5000,'2012-11-12'
UNION ALL
SELECT 'Name8','','工程部',3000,'2012-11-12'
UNION ALL
SELECT 'Name9','','工程部',6000,'2011-11-12'
UNION ALL
SELECT 'Name10','','工程部',3000,'2011-11-12'
UNION ALL
SELECT 'Name11','','技術部',3000,'2011-11-12'
 

 

GROUP BY 分組查詢, 通常和聚合函數配合使用性能

SELECT  [DEPARTMENT],SEX, COUNT(1)
FROM DBO.[STAFF] 
GROUP BY SEX, [DEPARTMENT]  

該段SQL是用於查詢   某個部門下的男女員工數量 其數據結果以下
spa

開銷比較大 code

 

GROUPING SETShtm

使用 GROUPING SETS 的 GROUP BY 子句能夠生成一個等效於由多個簡單 GROUP BY 子句的 UNION ALL 生成的結果集,而且其效率比 GROUP BY 要高,SQL Server 2008引入。 blog

1.使用GROUP BY 子句的 UNION ALL 來統計 Staff 表中的性別、部門、薪資、入職年份內存

SET STATISTICS IO ON  
SET STATISTICS TIME ON

SELECT N'總人數' ,'',COUNT(0) FROM [DBO].[STAFF]
UNION ALL  
SELECT N'按性別劃分', SEX,COUNT(0) FROM  [DBO].[STAFF] GROUP BY SEX  
UNION ALL  
SELECT N'按部門統計',[DEPARTMENT],COUNT(0) FROM  [DBO].[STAFF] GROUP BY [DEPARTMENT]  
UNION ALL  
SELECT N'按薪資統計',CONVERT(VARCHAR(10),[MONEY]),COUNT(0) FROM  [DBO].[STAFF] GROUP BY  [MONEY] 
UNION ALL  
SELECT N'按入職年份',CONVERT(VARCHAR(10),YEAR([CREATEDATE])),COUNT(0) FROM  [DBO].[STAFF] GROUP BY YEAR([CREATEDATE])  
 


2.換成GROUPING SETS的寫法class

SET STATISTICS IO ON  
SET STATISTICS TIME ON  
GO
SELECT (CASE  
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=15 THEN N'總人數' 
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=7 THEN N'按性別劃分'  
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=11 THEN N'按部門統計'  
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=13 THEN N'按薪資統計'   
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=14 THEN N'按入職年份'   
END  
),
(CASE  
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=15 THEN ''
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=7 THEN SEX  
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=11 THEN [DEPARTMENT]  
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=13 THEN CONVERT(VARCHAR(10),[MONEY])   
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=14 THEN CONVERT(VARCHAR(10),YEAR([CREATEDATE]))   
END  
) 
,
COUNT(1) 
FROM DBO.[STAFF]
GROUP BY GROUPING SETS (SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]),())
 

從上述結果中能夠看出,採用UNION ALL 是屢次掃描表,並將掃描後的查詢結果進行組合操做,會增長IO開銷,減小CPU和內存開銷。效率

採用GROUPING SETS 是一次性讀取全部數據,並在內存中進行聚合操做生成結果,減小IO開銷,對CPU和內存消耗增長。但GROUPING SETS 在多列分組時,其性能會比group by高。

這裏掃描四次是由於我 GROUP BY GROUPING SETS (SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]),()) 了四列

 

ROLLUP與CUBE 

ROLLUP與CUBE  按必定的規則產生多種分組,而後按各類分組統計數據

ROLLUP與CUBE 區別:

  CUBE 會對全部的分組字段進行統計,而後合計。

  ROLLUP 按照分組順序,對第一個字段進行組內統計,最後給出合計。
 
下面看我查詢 
SELECT  
      CASE WHEN (GROUPING(SEX) = 1) THEN '統計-ROLLUP' 
            ELSE ISNULL(SEX, 'UNKNOWN') 
       END AS SEX ,
        COUNT(0)
FROM DBO.[STAFF] 
GROUP BY   SEX   WITH ROLLUP

SELECT  
      CASE WHEN (GROUPING(SEX) = 1) THEN '統計-CUBE' 
            ELSE ISNULL(SEX, 'UNKNOWN') 
       END AS SEX ,
        COUNT(0)
FROM DBO.[STAFF] 
GROUP BY   SEX   WITH CUBE

看不出差異,咱們再加一列
SELECT  
      CASE WHEN (GROUPING(SEX) = 1) THEN '統計-ROLLUP' 
            ELSE ISNULL(SEX, 'UNKNOWN') 
       END AS SEX , 
      CASE WHEN (GROUPING([DEPARTMENT]) = 1) THEN '統計-ROLLUP' 
            ELSE ISNULL([DEPARTMENT], 'UNKNOWN') 
       END AS [DEPARTMENT], 
        COUNT(0) 
FROM DBO.[STAFF] 
GROUP BY   SEX,[DEPARTMENT]   WITH ROLLUP

SELECT  
      CASE WHEN (GROUPING(SEX) = 1) THEN '統計-CUBE' 
            ELSE ISNULL(SEX, 'UNKNOWN') 
       END AS SEX ,
      CASE WHEN (GROUPING([DEPARTMENT]) = 1) THEN  '統計-CUBE' 
            ELSE ISNULL([DEPARTMENT], 'UNKNOWN') 
       END AS [DEPARTMENT], 
        COUNT(0) 
FROM DBO.[STAFF] 
GROUP BY   SEX,[DEPARTMENT]  WITH CUBE

能夠看出 使用 ROLLUP 會先統計分組下的,而後在對GROUP BY的第一列字段進行統計,最後計算總數,而 CUBE 則是先分組統計,而後統計GRUOP BY 的每一個字段,最後進行彙總。

 

 http://www.cnblogs.com/woxpp/p/4688715.html 

相關文章
相關標籤/搜索