如何对具有多个聚合的表使用SQL表透视
我有一个返回下表的过程: 我想围绕它旋转,这样对于返回的每个名称,都有一行表示计划、实际和差异 例如:如何对具有多个聚合的表使用SQL表透视,sql,tsql,pivot,Sql,Tsql,Pivot,我有一个返回下表的过程: 我想围绕它旋转,这样对于返回的每个名称,都有一行表示计划、实际和差异 例如: | Key | Name1 | Name2 | Name3 | Name4 | Planned | 0 | 0 | 0 | 0 | Actual | 8957 | 5401 | NULL | NULL |Difference| -8957 | -5401 | NULL | NULL 我
| Key | Name1 | Name2 | Name3 | Name4
| Planned | 0 | 0 | 0 | 0
| Actual | 8957 | 5401 | NULL | NULL
|Difference| -8957 | -5401 | NULL | NULL
我正在尝试使用PIVOT函数,但我以前从未使用过它,我正在努力让我的头脑绕过它。如何实现与上述类似的功能?如果没有轴,可以使用交叉连接
create table #T
(
Name varchar(255),
Planned int,
Actual int,
[Difference] int
)
insert into #T(Name, Planned, Actual, [Difference])
select 'Name1', 0, 8957, -8957
union
select 'Name2', 0, 5401, -5401
union
select 'Name3', 0, NULL, NULL
union
select 'Name4', 0, NULL, NULL
-- unpivoting data
create table #T2
(
[Key] varchar(255),
Name varchar(255),
Value int
)
insert into #T2
select [Key], Name, Value
from
(select Name, Planned, Actual, [Difference] from #T) P
UNPIVOT
(Value for [Key] IN (Planned, Actual, [Difference])) as UNP
-- getting sequence of column names
declare @columns nvarchar(max)
set @columns = ''
select @columns = @columns + ', [' + Name + ']'
from (select distinct Name from #T2) as T
order by Name
set @columns = substring(@columns, 2, len(@columns))
declare @sql nvarchar(max)
-- building dynamic sql for pivoting
set @sql =
'
SELECT *
FROM
(SELECT
[Key], Name, Value
FROM
#T2
) AS SourceTable
PIVOT
(
SUM(Value)
FOR Name in ('+@columns+')
) AS PivotTable
order by
case [Key]
when ''Planned'' then 1
when ''Actual'' then 2
when ''Difference'' then 3 end
'
exec sp_executeSQL @SQL
drop table #T2
drop table #T
注意,只有当您知道每次运行时将有多少个名称,并且每个名称在原始表中只出现一次时,此功能才有效。(否则,下面的max函数不适用)
如果不明确知道名称,则需要一个动态轴心。只需谷歌“SQLServerDynamicPivot”,您就可以获得示例。否则,请参阅Microsoft文档中的
pivot
。您可能需要先unpivot
,以生成12行Name
和Status
列以及所有12个不同行中的值,然后基于此生成pivot
。
create table #test(ID int, Name char(5), planned int, actual int, difference_between int)
insert into dbo.#test
values
(54, 'Name1', 0, 8975, -8957),
(54, 'Name2', 0, 5401, -5401),
(54, 'Name3', 0, NULL, NULL),
(54, 'Name4', 0, NULL, NULL)
select case t.occurno when 1 then 'Planned' when 2 then 'Actual' when 3 then 'Difference' end as [Key]
, max(case when Name = 'name1' then case t.occurno when 1 then planned when 2 then actual when 3 then difference_between else 0 end end) as Name1
, max(case when Name = 'name2' then case t.occurno when 1 then planned when 2 then actual when 3 then difference_between else 0 end end) as name2
, max(case when Name = 'name3' then case t.occurno when 1 then planned when 2 then actual when 3 then difference_between else 0 end end) as name3
, max(case when Name = 'name4' then case t.occurno when 1 then planned when 2 then actual when 3 then difference_between else 0 end end) as name4
from dbo.#test
cross join
(select top 3 ROW_NUMBER() over(order by occurno) as occurno
from (select 1 as occurno) t
group by cube(occurno,occurno,occurno,occurno)
) t
group by t.occurno