SQL Server 使用 WITH ROLLUP, CUBE, GROUPING 如何汇总数据

96 阅读4分钟

表架构及数据

表架构及数据SQL

CREATE TABLE [dbo].[temp_order](
	[rowid] [int] IDENTITY(1,1) NOT NULL,
	[c_type] [varchar](20) NULL,
	[c_number] [decimal](18, 2) NULL,
	[c_sumprice] [decimal](18, 2) NULL,
	[purchaser] [nvarchar](50) NULL
) ON [PRIMARY]

INSERT [dbo].[temp_order] ([rowid], [c_type], [c_number], [c_sumprice], [purchaser]) VALUES (1, N'A', CAST(1.00 AS Decimal(18, 2)), CAST(100.00 AS Decimal(18, 2)), N'MicroSoft')
INSERT [dbo].[temp_order] ([rowid], [c_type], [c_number], [c_sumprice], [purchaser]) VALUES (2, N'B', CAST(2.00 AS Decimal(18, 2)), CAST(400.00 AS Decimal(18, 2)), N'Google')
INSERT [dbo].[temp_order] ([rowid], [c_type], [c_number], [c_sumprice], [purchaser]) VALUES (3, N'C', CAST(3.00 AS Decimal(18, 2)), CAST(900.00 AS Decimal(18, 2)), N'Apple')
INSERT [dbo].[temp_order] ([rowid], [c_type], [c_number], [c_sumprice], [purchaser]) VALUES (4, N'A', CAST(6.00 AS Decimal(18, 2)), CAST(600.00 AS Decimal(18, 2)), N'Google')
INSERT [dbo].[temp_order] ([rowid], [c_type], [c_number], [c_sumprice], [purchaser]) VALUES (5, N'B', CAST(0.50 AS Decimal(18, 2)), CAST(100.00 AS Decimal(18, 2)), N'Apple')
INSERT [dbo].[temp_order] ([rowid], [c_type], [c_number], [c_sumprice], [purchaser]) VALUES (6, N'C', CAST(2.00 AS Decimal(18, 2)), CAST(600.00 AS Decimal(18, 2)), N'MicroSoft')

初始数据

SELECT * FROM TEMP_ORDER
rowidc_typec_numberc_sumpricepurchaser
1A1100MicroSoft
2B2400Google
3C3900Apple
4A6600Google
5B0.5100Apple
6C2600MicroSoft

普通分组

按购买方和货物类别分组,求和货物数量

select purchaser,c_type,sum(c_number) g_num from temp_order
group by purchaser,c_type
purchaserc_typeg_num
GoogleA6
MicroSoftA1
AppleB0.5
GoogleB2
AppleC3
MicroSoftC2

with cube

CUBE:CUBE 生成的结果集显示了所选列中值的所有组合的聚合。分类依据根据group by中的顺序,列显示顺序根据select中的顺序。

顺序1

观察结果发现显示顺序为:先按照最后的c_type分组条件求和,再求总和,最后按照purchaser分组条件求和。

select purchaser,c_type,sum(c_number) g_num from temp_order
group by purchaser,c_type
with cube
purchaserc_typeg_num
GoogleA6
MicroSoftA1
NULLA7
AppleB0.5
GoogleB2
NULLB2.5
AppleC3
MicroSoftC2
NULLC5
NULLNULL14.5
AppleNULL3.5
GoogleNULL8
MicroSoftNULL3

顺序2

与顺序1相比,只更换select中的顺序。观察结果发现g_num列结果并未产生行顺序改变。

select c_type,purchaser,sum(c_number) g_num from temp_order
group by purchaser,c_type
with cube
c_typepurchaserg_num
AGoogle6
AMicroSoft1
ANULL7
BApple0.5
BGoogle2
BNULL2.5
CApple3
CMicroSoft2
CNULL5
NULLNULL14.5
NULLApple3.5
NULLGoogle8
NULLMicroSoft3

顺序3

与顺序1相比,只更换group by中的顺序。观察结果发现g_num列结果产生行顺序改变,得出分类依据根据group by中的顺序。

select purchaser,c_type,sum(c_number) g_num from temp_order
group by c_type,purchaser
with cube
purchaserc_typeg_num
AppleB0.5
AppleC3
AppleNULL3.5
GoogleA6
GoogleB2
GoogleNULL8
MicroSoftA1
MicroSoftC2
MicroSoftNULL3
NULLNULL14.5
NULLA7
NULLB2.5
NULLC5

with rollup

ROLLUP:ROLLUP 生成的结果集显示了所选列中值的某一层次结构的聚合。某一层次结构跟group by的第一个分组条件有关。

顺序1

观察结果发现对第一个purchaser分组条件进行求和,并按所有分组条件求总和。

select purchaser,c_type,sum(c_number) g_num from temp_order
group by purchaser,c_type
with rollup
purchaserc_typeg_num
AppleB0.5
AppleC3
AppleNULL3.5
GoogleA6
GoogleB2
GoogleNULL8
MicroSoftA1
MicroSoftC2
MicroSoftNULL3
NULLNULL14.5

顺序2

与顺序1相比,更换group by中的顺序。观察结果发现对第一个c_type分组条件进行求和,并按所有分组条件求总和。得出某一层次结构跟group by的第一个分组条件有关。

select purchaser,c_type,sum(c_number) g_num from temp_order
group by c_type,purchaser
with rollup
purchaserc_typeg_num
GoogleA6
MicroSoftA1
NULLA7
AppleB0.5
GoogleB2
NULLB2.5
AppleC3
MicroSoftC2
NULLC5
NULLNULL14.5

grouping

GROUPING:当行由 CUBE 或 ROLLUP 运算符添加时,该函数将导致附加列的输出值为 1;当行不由 CUBE 或 ROLLUP 运算符添加时,该函数将导致附加列的输出值为 0。

顺序1

观察结果发现只有最后一行的purchaser值为ROLLUP 运算符添加,grouping(purchaser)=1

select purchaser,c_type,sum(c_number) g_num,grouping(purchaser) from temp_order
group by purchaser,c_type
with rollup
purchaserc_typeg_num(无列名)
AppleB0.50
AppleC30
AppleNULL3.50
GoogleA60
GoogleB20
GoogleNULL80
MicroSoftA10
MicroSoftC20
MicroSoftNULL30
NULLNULL14.51

顺序2

观察结果发现所有行的c_type值为ROLLUP 运算符添加时,grouping(c_type)=1

select purchaser,c_type,sum(c_number) g_num,grouping(c_type) from temp_order
group by purchaser,c_type
with rollup
purchaserc_typeg_num(无列名)
AppleB0.50
AppleC30
AppleNULL3.51
GoogleA60
GoogleB20
GoogleNULL81
MicroSoftA10
MicroSoftC20
MicroSoftNULL31
NULLNULL14.51

实战:实现显示小计和总计

按购买方和货物类别分组,求和货物数量并显示小计和总计。

select purchaser,
	case when grouping(purchaser)=1 then '总计'
	else
		case when grouping(c_type)=1 then '小计'
		else c_type
		end
	end 'c_type'
,sum(c_number) g_num from temp_order
group by purchaser,c_type
with rollup
purchaserc_typeg_num
AppleB0.5
AppleC3
Apple小计3.5
GoogleA6
GoogleB2
Google小计8
MicroSoftA1
MicroSoftC2
MicroSoft小计3
NULL总计14.5