目前有一个脚本可以创建一个数据透视表,其当前年份值减去上一年的值。
use devmreports
-- Creates dynamic values for pivot table
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(month)
from ABR
group by ',' + QUOTENAME(month)
order by datalength(',' + QUOTENAME(month))
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
-- Pivot table for YOY change in booked passengers
set @query
=
'SELECT Region,
CityPair,
Year,
' + @cols + '
FROM
(
SELECT ABR.Region,
ABR.CityPair,
ABR.Year,
ABR.Month,
ABR.Adv_B - ABRP.Adv_B as Total
FROM ABR LEFT OUTER JOIN
ABRP ON
ABR.Month = ABRP.Month AND
ABR.CityPair = ABRP.CityPair) P
PIVOT
(
SUM(Total)
FOR MONTH IN
(
'+@cols+'))as pvt'
execute (@Query)
Current Pivot看起来像这样:
+------------+----------+----+-----+-----+----+
| Region | CityPair | 8 | 9 | 10 | 11 |
+------------+----------+----+-----+-----+----+
| A | 1 | 16 | 17 | 18 | 7 |
| A | 2 | 17 | -20 | -10 | 1 |
| B | 3 | 5 | 8 | 4 | -3 |
| B | 4 | 21 | 10 | 3 | 2 |
| C | 5 | 15 | -14 | -12 | 1 |
+------------+----------+----+-----+-----+----+
我想要的是:
+-----------------+----------+----+-----+-----+----+
| Region | CityPair | 8 | 9 | 10 | 11 |
+-----------------+----------+----+-----+-----+----+
| A | 1 | 16 | 17 | 18 | 7 |
| A | 2 | 17 | -20 | -10 | 1 |
| A Total | | 33 | -3 | 8 | 8 |
| B | 3 | 5 | 8 | 4 | -3 |
| B | 4 | 21 | 10 | 3 | 2 |
| B Total | | 26 | 18 | 7 | -1 |
| C | 5 | 15 | -14 | -12 | 1 |
| C Total | | 15 | -14 | -12 | 1 |
| Grand Total | | 74 | 1 | 3 | 8 |
+-----------------+----------+----+-----+-----+----+
非常感谢任何协助。
答案 0 :(得分:3)
我的建议是使用GROUP BY ROLLUP
来获取总行数。
如果您对查询进行硬编码,则基本语法为:
select
case
when region is null then 'Grand Total'
when citypair is null then region +' Total'
else region end region,
coalesce(cast(citypair as varchar(10)), '') citypair,
sum([8]) [8],
sum([9]) [9]
from
(
select region, citypair, month, total
from yourtable
) d
pivot
(
sum(total)
for month in ([8], [9])
) piv
GROUP BY rollup(region, citypair);
见SQL Fiddle with Demo。然后,要使用动态SQL版本,您可以更改要使用的代码:
-- Creates dynamic values for pivot table
DECLARE @cols AS NVARCHAR(MAX),
@colsRollup AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(month)
from ABR
group by ',' + QUOTENAME(month)
order by datalength(',' + QUOTENAME(month))
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @colsRollup = STUFF((SELECT ', sum(' + QUOTENAME(month)+ ') as '+ QUOTENAME(month)
from ABR
group by ',' + QUOTENAME(month)
order by datalength(',' + QUOTENAME(month))
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
-- Pivot table for YOY change in booked passengers
set @query
=
'SELECT
case
when region is null then ''Grand Total''
when citypair is null then region +'' Total' '
else region end region,
coalesce(cast(citypair as varchar(10)), '''') citypair,
' + @colsRollup + '
FROM
(
SELECT ABR.Region,
ABR.CityPair,
ABR.Year,
ABR.Month,
ABR.Adv_B - ABRP.Adv_B as Total
FROM ABR LEFT OUTER JOIN
ABRP ON
ABR.Month = ABRP.Month AND
ABR.CityPair = ABRP.CityPair
) P
PIVOT
(
SUM(Total)
FOR MONTH IN ('+@cols+')
)as pvt
GROUP BY rollup(region, citypair);'
execute sp_executesql @Query
答案 1 :(得分:0)
这就是为什么我更喜欢用聚合而不是pivot
手动转动。这是一个查询,它将显示总计和总计的所有总和:
select
case
when grouping(Region) = 1 then 'Grand Total'
when grouping(CityPair) = 1 then Region + ' Total'
else Region
end as Region,
isnull(cast(CityPair as nvarchar(max)), '') as CityPair,
sum(case when Month = 8 then Value end) as [8],
sum(case when Month = 9 then Value end) as [9],
sum(case when Month = 10 then Value end) as [10],
sum(case when Month = 11 then Value end) as [11]
from test
group by rollup(Region, CityPair)
这是动态的:
declare @stmt nvarchar(max)
select
@stmt = isnull(@stmt + ',', '') +
'sum(case when Month = ' + cast(Month as nvarchar(max)) +
' then Value end) as [' + cast(Month as nvarchar(max)) + ']'
from (select distinct Month from test) as a
select @stmt = '
select
case
when grouping(Region) = 1 then ''Grand Total''
when grouping(CityPair) = 1 then Region + '' Total''
else Region
end as Region,
isnull(cast(CityPair as nvarchar(max)), ''''), ' + @stmt + '
from test
group by rollup(Region, CityPair)'
exec sp_executesql @stmt = @stmt
一如既往,尽量让它尽可能可读。
我建议使用group by rollup代替with rollup,因为最后一个将被弃用:
WITH ROLLUP此功能将在以后的版本中删除 Microsoft SQL Server。避免在新开发中使用此功能 工作,并计划修改当前使用此功能的应用程序。