在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/