SQL pivot不处理数据缺失

时间:2017-08-29 13:47:49

标签: sql-server pivot

我有一张桌子

Create table dbo.temp(ID int, ExpenseID int, ExpenseName Varchar(100) null, ExpenseDate date null, Value decimal(19,4) null)
  Insert into dbo.temp values(1,100,'CostClothes','2015-01-01',100.0000)
  Insert into dbo.temp values(1,200,'Discount','2015-01-01',1.0000)

  Insert into dbo.temp values(2,100,'CostClothes','2016-01-01',250.0000)
  Insert into dbo.temp values(2,200,'Discount','2016-01-01',1.0000)

  Insert into dbo.temp values(1,100,'CostClothes','2014-01-01',500.0000)
  Insert into dbo.temp values(2,200,'Discount','2014-01-01',5.0000)

现在我想在ExpenseID上转移此表,预期输出为

Create table dbo.output(ID int, CostClothes decimal(19,4) null, Discount  decimal(19,4) null, ExpenseDate date null)
  insert into dbo.output values (1,100.0000,1.0000,'2015-01-01')
  insert into dbo.output values (1,500.0000,NULL,'2014-01-01')
  insert into dbo.output values (2,NULL,5.0000,'2014-01-01')  
  insert into dbo.output values (2,100.0000,1.0000,'2016-01-01') 

这就是我所拥有的,我没有得到正确的输出

SELECT ID,ISNULL([100],0) as CostClothes,ISNULL([200],0) as Discount,expenseDate
  FROM
  (
  SELECT * FROM dbo.temp
  ) AS p 
  PIVOT
  (
    MAX(Value) for ExpenseID in ([100],[200])
  ) AS PV1

如何更改查询

由于 MR

2 个答案:

答案 0 :(得分:1)

给定样本数据,您可以使用聚合进行数据透视,也可以只进行简单的条件聚合。

select
    ID
    ,max(case when ExpenseName = 'CostClothes' then Value end) as CostClothes
    ,max(case when ExpenseName = 'Discount' then Value end) as Discount
    ,ExpenseDate
from
    dbo.temp
group by
    ID
    ,ExpenseDate
order by
    ID

数据透视法

select
    ID
    ,CostClothes = max(CostClothes)
    ,Discount = max(Discount)
    ,ExpenseDate
from
    dbo.temp
pivot(
    max(Value) for ExpenseName in (CostClothes, Discount)
) p
group by
    ID
    ,ExpenseDate
order by
    ID

演示: http://rextester.com/ENHTIK13664

答案 1 :(得分:0)

您的问题是您在派生表中选择了太多信息。

如果您要使用Select *,则甚至不需要派生表。使用PIVOT时,您应该只选择最终结果中需要的字段。与编写条件聚合查询的方式相同。

SELECT ID,
       ISNULL([100], 0) AS CostClothes,
       ISNULL([200], 0) AS Discount,
       expenseDate
FROM
(
    SELECT ID,
           ExpenseID,
           ExpenseDate,
           Value
    FROM   temp
) AS p PIVOT(MAX(Value) FOR ExpenseID IN([100],[200])) AS PV1

这可以通过删除ExpenseName列来为您提供所需的结果。或者您可以使用ExpenseName列并删除ExpenseID