在SQL Server裏,你有沒有想進行跨越多個列/緯度的彙集操做,不使用SSAS許可(SQL Server分析服務)。我不是說在生產裏使用開發版,也不是說安裝盜版SQL Server。sql
不可能的任務?未必,由於經過SQL Server裏所謂的Grouping Sets就能夠。在這篇文章裏我會給你歸納介紹下Grouping Sets,使用它們能夠實現哪類查詢,什麼是它們的性能優點。數據庫
假設你有個訂單表,你想進行跨多個分組的T-SQL彙集查詢。在AdventureWorks2012數據庫的Sales.SalesOrderHeader表的環境裏,這些分組能夠相似以下:
性能
當你想用傳統T-SQL查詢進行這些各自分組時,你須要多個語句,對各個記錄集進行UNION ALL。咱們來看這樣的查詢:spa
1 SELECT * FROM 2 ( 3 -- 1st Grouping Set 4 SELECT 5 NULL AS 'CustomerID', 6 NULL AS 'SalesPersonID', 7 NULL AS 'OrderYear', 8 SUM(TotalDue) AS 'TotalDue' 9 FROM Sales.SalesOrderHeader 10 WHERE SalesPersonID IS NOT NULL 11 12 UNION ALL 13 14 -- 2nd Grouping Set 15 SELECT 16 NULL AS 'CustomerID', 17 SalesPersonID, 18 YEAR(OrderDate) AS 'OrderYear', 19 SUM(TotalDue) AS 'TotalDue' 20 FROM Sales.SalesOrderHeader 21 WHERE SalesPersonID IS NOT NULL 22 GROUP BY SalesPersonID, YEAR(OrderDate) 23 24 UNION ALL 25 26 -- 3rd Grouping Set 27 SELECT 28 CustomerID, 29 NULL AS 'SalesPersonID', 30 YEAR(OrderDate) AS 'OrderYear', 31 SUM(TotalDue) AS 'TotalDue' 32 FROM Sales.SalesOrderHeader 33 WHERE SalesPersonID IS NOT NULL 34 GROUP BY CustomerID, YEAR(OrderDate) 35 36 UNION ALL 37 38 -- 4th Grouping Set 39 SELECT 40 CustomerID, 41 SalesPersonID, 42 YEAR(OrderDate) AS 'OrderYear', 43 SUM(TotalDue) AS 'TotalDue' 44 FROM Sales.SalesOrderHeader 45 WHERE SalesPersonID IS NOT NULL 46 GROUP BY CustomerID, SalesPersonID, YEAR(OrderDate) 47 ) AS t 48 ORDER BY CustomerID, SalesPersonID, OrderYear 49 GO
用這個T-SQL語句方法有多個缺點:code
若是你使用自SQL Server 2008之後引入的grouping sets功能,就能夠大大簡化你須要的T-SQL代碼。下面代碼展現你一樣的查詢,但此次用grouping sets實現。server
1 SELECT 2 CustomerID, 3 SalesPersonID, 4 YEAR(OrderDate) AS 'OrderYear', 5 SUM(TotalDue) AS 'TotalDue' 6 FROM Sales.SalesOrderHeader 7 WHERE SalesPersonID IS NOT NULL 8 GROUP BY GROUPING SETS 9 ( 10 -- Our 4 different grouping sets 11 (CustomerID, SalesPersonID, YEAR(OrderDate)), 12 (CustomerID, YEAR(OrderDate)), 13 (SalesPersonID, YEAR(OrderDate)), 14 () 15 ) 16 GO
從代碼自己能夠看到,你只在GROUP BY GROUPING SETS子句裏指定須要的分組集——其它的一切都由SQL Server搞定。指定的空括號是所謂的Empty Grouping Set,是跨整個表的彙集。當你看STATISTICS IO輸出時,你會發現Sales.SalesOrderHeader只被訪問了1次!這是和剛纔手工實現的巨大區別。blog
在執行計劃裏,SQL Server使用了Table Spool運算符,它把得到的數據臨時存儲在TempDb裏。來自臨時表裏建立的Worktable的數據在執行計劃的第2個分支被使用。所以對來自表的每一個分組數據沒有從新掃描,這就給整個執行計劃的帶來了更好的性能。索引
咱們再來看下執行計劃,你會發現查詢計劃包含了3個Stream Aggregate運算符(紅色,藍色,綠色高亮顯示)。這3個運算符計算各個分組集:開發
2個連續的Stream Aggregate運算符的背後想法是計算所謂的Super Aggregates——彙集的彙集。get
在今天的文章裏我給你介紹了grouping sets,在SQL Server 2008後引入的加強T-SQL。如你所見grouping sets有2個大優勢:簡化你的代碼,只訪問一次數據提升查詢性能。
我但願如今你已經可以很好理解grouping sets,若是你能在你的數據庫裏使用這個功能能夠在此留言,很是感謝!
感謝關注!
https://www.sqlpassion.at/archive/2014/09/15/the-power-of-grouping-sets-in-sql-server/