国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > SQL Server > 正文

SQL Server里Grouping Sets的威力

2024-08-31 00:54:10
字體:
來源:轉載
供稿:網友
SQL Server里Grouping Sets的威力

在SQL Server里,你有沒有想進行跨越多個列/緯度的聚集操作,不使用SSAS許可(SQL Server分析服務)。我不是說在生產里使用開發版,也不是說安裝盜版SQL Server。

不可能的任務?未必,因為通過SQL Server里所謂的Grouping Sets就可以。在這篇文章里我會給你概括介紹下Grouping Sets,使用它們可以實現哪類查詢,什么是它們的性能優勢。

使用Grouping Sets的聚合

假設你有個訂單表,你想進行跨多個分組的T-SQL聚集查詢。在AdventureWorks2012數據庫的Sales.SalesOrderHeader表的環境里,這些分組可以類似如下:

  • 在每列分組
  • GROUP BY SalesPersonID, YEAR(OrderDate)
  • GROUP BY CustomerID, YEAR(OrderDate)
  • GROUP BY CustomerID, SalesPersonID, YEAR(OrderDate)

當你想用傳統T-SQL查詢進行這些各自分組時,你需要多個語句,對各個記錄集進行UNION ALL。我們來看這樣的查詢:

 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.SalesOrderHeader10     WHERE SalesPersonID IS NOT NULL11 12     UNION ALL13 14     -- 2nd Grouping Set15     SELECT16         NULL AS 'CustomerID',17         SalesPersonID, 18         YEAR(OrderDate) AS 'OrderYear', 19         SUM(TotalDue) AS 'TotalDue' 20     FROM Sales.SalesOrderHeader21     WHERE SalesPersonID IS NOT NULL22     GROUP BY SalesPersonID, YEAR(OrderDate)23 24     UNION ALL25 26     -- 3rd Grouping Set27     SELECT28         CustomerID,29         NULL AS 'SalesPersonID', 30         YEAR(OrderDate) AS 'OrderYear', 31         SUM(TotalDue) AS 'TotalDue' 32     FROM Sales.SalesOrderHeader33     WHERE SalesPersonID IS NOT NULL34     GROUP BY CustomerID, YEAR(OrderDate)35 36     UNION ALL37 38     -- 4th Grouping Set39     SELECT40         CustomerID,41         SalesPersonID,42         YEAR(OrderDate) AS 'OrderYear', 43         SUM(TotalDue) AS 'TotalDue' 44     FROM Sales.SalesOrderHeader45     WHERE SalesPersonID IS NOT NULL46     GROUP BY CustomerID, SalesPersonID, YEAR(OrderDate)47 ) AS t48 ORDER BY CustomerID, SalesPersonID, OrderYear49 GO

用這個T-SQL語句方法有多個缺點:

  • T-SQL語句本身很龐大,因為每個單獨分組都是一個不同查詢。
  • 每查詢1次,Sales.SalesOrderHeader表需要訪問4次。
  • 每查詢1次,你在執行計劃里會看到SQL Server進行了4次的索引查找(非聚集)(Index Seek (NonClustered))

如果你使用自SQL Server 2008以后引入的grouping sets功能,就可以大大簡化你需要的T-SQL代碼。下面代碼展示你同樣的查詢,但這次用grouping sets實現。

 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 sets11     (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次!這是和剛才手工實現的巨大區別。

在執行計劃里,SQL Server使用了Table Spool運算符,它把獲得的數據臨時存儲在TempDb里。來自臨時表里創建的Worktable的數據在執行計劃的第2個分支被使用。因此對來自表的每個分組數據沒有重新掃描,這就給整個執行計劃的帶來了更好的性能。

我們再來看下執行計劃,你會發現查詢計劃包含了3個Stream Aggregate運算符(紅色,藍色,綠色高亮顯示)。這3個運算符計算各個分組集:

  • 藍色高亮的運算符計算CustomerID, SalesPersonID, YEAR(OrderDate的分組集。
  • 紅色高亮的運算符計算SalesPersonID, YEAR(OrderDate)的分組集。另外也計算每1列的分組集。
  • 綠色高亮的運算符計算CustomerID, YEAR(OrderDate)的分組集。

2個連續的Stream Aggregate運算符的背后想法是計算所謂的Super Aggregates——聚集的聚集。

小結

在今天的文章里我給你介紹了grouping sets,在SQL Server 2008后引入的增強T-SQL。如你所見grouping sets有2個大優點:簡化你的代碼,只訪問一次數據提高查詢性能。

我希望現在你已經能夠很好理解grouping sets,如果你能在你的數據庫里使用這個功能可以在此留言,非常感謝!

感謝關注!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 罗田县| 松滋市| 牙克石市| 合阳县| 衡阳市| 沾化县| 咸阳市| 河北区| 丹巴县| 聂荣县| 兰坪| 通海县| 沙雅县| 金溪县| 郴州市| 寻乌县| 大埔县| 扎囊县| 龙州县| 桓台县| 齐齐哈尔市| 和顺县| 天水市| 习水县| 金川县| 梁山县| 玉树县| 明水县| 平顺县| 江永县| 黄浦区| 迭部县| 玉门市| 开阳县| 大名县| 林周县| 襄垣县| 马山县| 西乌珠穆沁旗| 武隆县| 德清县|