如何对具有多个聚合的表使用SQL表pivot

时间:2014-06-20 10:08:42

标签: sql tsql pivot

我有一个返回下表的过程:

enter image description here

我想绕过它,以便对于返回的每个Name,你有一行计划,实际和差异。

例如:

|    Key   | Name1  |  Name2  |  Name3  |  Name4
| Planned  |   0    |    0    |    0    |    0 
|  Actual  |  8957  |   5401  |   NULL  |   NULL
|Difference| -8957  |  -5401  |   NULL  |   NULL

我正在尝试使用PIVOT功能,但我以前从未使用它,并且正在努力解决它。如何实现与上述类似的东西?

2 个答案:

答案 0 :(得分:1)

如果没有支点,您可以使用交叉连接

请注意,只有当您知道每次运行它时会有多少名称,并且每个名称只在原始表中出现一次时,这才有效。(否则下面的最大函数不合适) < / p>

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

答案 1 :(得分:0)

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