SQL SERVER中GROUPING SETS,CUBE,ROLLUP
前言
with test
as
(
select N'LeeWhoeeUnisersity' as name,N'数据库' as category, 30 as totalcount
union all
select N'LeeWhoeeUnisersity','.NET',20
union all
select N'DePaul',N'.NET',40
union all
select N'DePaul',N'WEB设计',30
)
select * from test
结果集是:
name category totalcount
LeeWhoeeUnisersity 数据库 30
LeeWhoeeUnisersity .NET 20
DePaul .NET 40
DePaul WEB设计 30
GROUPING SETS
SELECT customer, year, SUM(sales)
FROM T
GROUP BY GROUPING SETS ((customer), (year))
和
SELECT customer, NULL as year, SUM(sales)
FROM T
GROUP BY customer
UNION ALL
SELECT NULL as customer, year, SUM(sales)
FROM T
GROUP BY year
是等效的。
看实例:
with test
as
(
select N'LeeWhoeeUnisersity' as name,N'数据库' as category, 30 as totalcount
union all
select N'LeeWhoeeUnisersity','.NET',20
union all
select N'DePaul',N'.NET',40
union all
select N'DePaul',N'WEB设计',30
)
select name,category,sum(totalcount) as [sum] from test
group by grouping sets ((name),(category))
结果:
name | category | sum |
---|---|---|
.NET | 60 | |
WEB设计 | 30 | |
数据库 | 30 | |
DePaul | 70 | |
LeeWhoeeUnisersity | 50 |
ROLLUP
GROUP BY ROLLUP (C1, C2, …, Cn-1, Cn)或者GROUP BY C1, C2, …, Cn-1, Cn WITH ROLLUP
和
GROUP BY GROUPING SETS ( (C1, C2, …, Cn-1, Cn)
,(C1, C2, ..., Cn-1)
...
,(C1, C2)
,(C1)
,() )
是等效的。注意WITH ROLLUP是旧版本的写法,GROUP BY ROLLUP 只能运行于兼容性100以上的版本。
with test
as
(
select N'LeeWhoeeUnisersity' as name,N'数据库' as category, 30 as totalcount
union all
select N'LeeWhoeeUnisersity','.NET',20
union all
select N'DePaul',N'.NET',40
union all
select N'DePaul',N'WEB设计',30
)
select name,category,sum(totalcount) as [sum] from test
group by rollup (name,category)
相当于
with test
as
(
select N'LeeWhoeeUnisersity' as name,N'数据库' as category, 30 as totalcount
union all
select N'LeeWhoeeUnisersity','.NET',20
union all
select N'DePaul',N'.NET',40
union all
select N'DePaul',N'WEB设计',30
)
select name,category,sum(totalcount) as [sum] from test
group by grouping sets ((name,category),(name),())
结果:
name | category | sum |
---|---|---|
DePaul | .NET | 40 |
DePaul | WEB设计 | 30 |
DePaul | 70 | |
LeeWhoeeUnisersity | .NET | 20 |
LeeWhoeeUnisersity | 数据库 | 30 |
LeeWhoeeUnisersity | 50 | |
120 |
CUBE
GROUP BY CUBE (C1, C2, C3)等效于GROUP BY GROUPING SETS ( (C1, C2, C3) ,(C1, C2) ,(C1, C3) ,(C2, C3) ,(C1) ,(C2) ,(C3) ,() )
进行CUBE测试:
with test
as
(
select N'LeeWhoeeUnisersity' as name,N'数据库' as category, 30 as totalcount
union all
select N'LeeWhoeeUnisersity','.NET',20
union all
select N'DePaul',N'.NET',40
union all
select N'DePaul',N'WEB设计',30
)
select case when grouping(name)=1 then 'allnames' else name end as name
,case when grouping(category)=1 then 'allcategories' else category end as category
,sum(totalcount) as sum
from test
group by cube(name,category)
相当于
with test
as
(
select N'LeeWhoeeUnisersity' as name,N'数据库' as category, 30 as totalcount
union all
select N'LeeWhoeeUnisersity','.NET',20
union all
select N'DePaul',N'.NET',40
union all
select N'DePaul',N'WEB设计',30
)
select case when grouping(name)=1 then 'allnames' else name end as name
,case when grouping(category)=1 then 'allcategories' else category end as category
,sum(totalcount) as sum
from test
group by grouping sets((name,category),(name),(category),())
结果:
name category sum
LeeWhoeeUnisersity .NET 20
DePaul .NET 40
allnames .NET 60
DePaul WEB设计 30
allnames WEB设计 30
LeeWhoeeUnisersity 数据库 30
allnames 数据库 30
allnames allcategories 120
LeeWhoeeUnisersity allcategories 50
DePaul allcategories 70
CUBE 生成的结果集显示了所选列中值的所有组合的聚合。
如果没有用CASE WHEN判断GROUPING,则上面所有的allnames,allcategories会被NULL替代。