使用If语句将行转置为列

时间:2017-01-31 14:20:43

标签: sql sql-server sql-server-2012

我正在尝试将某些行值转换为列。以下是我的表格:

ID  Item        Color   Quantity
1   Shoe        Red 
1   Shirt                3
1   Hat         Black   
1   Socks                2
1   Pants       Red 

我希望桌子看起来像这样:

ID  Shoe    Shirt   Hat    Socks    Pants
1   Red     3       Black   2       Red

以下是我正在使用的代码:

select Max(Case When [Item] = 'Shoe' Then Color End) as Shoe
    ,Max(Case When [Item] = 'Shirt' Then Quantity End) as Shirt
    ,Max(Case When [Item] = 'Hat' Then Color End) as Hat
    ,Max(Case When [Item] = 'Socks' Then Quantity End) as Socks
    ,Max(Case When [Item] = 'Pants' Then Color End) as Pants
From Inventory

我的代码有问题,有时行的值在列Color中,有时则在Number列中。我希望能够只使用具有值的列。我真正的select语句有超过50个Max(Case)语句,所以如果有一些我可以做一个总体if语句而不必为每一行做一个很棒的事情!

3 个答案:

答案 0 :(得分:2)

如果您事先了解所有项目,那么如何使用公用表表达式(CTE)查找项目中的非空值列,然后PIVOT。应该注意的是,这仅在其他值为null时有效,否则您需要检查''或0。

;WITH CTE
AS
(
    SELECT ID, Item, COALESCE(Color, CAST(Quantity AS VARCHAR(10))) AS Value
    FROM Inventory
)
select * from CTE
pivot (max (Value) for Item in ([Shoe],[Shirt],[Hat],[Socks],[Pants])) AS c

答案 1 :(得分:2)

如果您需要动态版本。

在下面的子查询中,您会注意到我们使用CONCAT(),它会正确处理NULL值。

Declare @Filter varchar(100) = 'Shoe,Socks'

Declare @SQL varchar(max) 
Select  @SQL = 'Select ID,' + '['+Replace(@Filter,',','],[')+']' + ' 
                From (
                       Select ID
                             ,Item
                             ,Value = concat(NullIf(Color,''''),NullIf(Quantity,0))
                       From  Inventory
                       Where charindex('',''+Item+'','','','+@Filter+','')>0
                     ) A
                Pivot (max(Value) For Item in (' + '['+Replace(@Filter,',','],[')+']' + ') ) p'
Exec(@SQL);
  

修改

NullIf()添加到concat()以捕获“空”值。

答案 2 :(得分:0)

您可能需要一个将项目映射到值列的字典。例如

select Max(Case When [Item] = 'Shoe' Then 
           Case col when 'Color' then Color else Quantity End 
           End) as Shoe
    ,Max(Case When [Item] = 'Shirt' Then  
           Case col when 'Color' then Color else Quantity End 
           End) as Shirt
    ,Max(Case When [Item] = 'Hat' Then 
           Case col when 'Color' then Color else Quantity End 
           End) as Hat
    ,Max(Case When [Item] = 'Socks' Then 
           Case col when 'Color' then Color else Quantity End 
           End) as Socks
    ,Max(Case When [Item] = 'Pants' Then 
           Case col when 'Color' then Color else Quantity End
           End) as Pants
From (
    select i.*, col
    from Inventory i
    join (
        values ('Shoe', 'Color') 
        ,('Shirt', 'Quantity')
        ,('Hat', 'Color')
        ,('Socks', 'Quantity')
        ,('Pants', 'Color')
        ) dict (itm, col) on dict.itm=t.item
) t