如何对具有多个聚合的表使用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