单列为N行

时间:2015-03-21 01:17:59

标签: sql sql-server pivot

我有一个包含3列的大表,如下所示:

Invoice Product     Color
1       Pant        Red
1       Pant        Black
1       Shirt       Green
2       Pant        White
2       Pant        Black
2       Pant        Blue

我想在Invoice& amp;产品然后将所有唯一的颜色值显示在相关的分组记录中,如下所示:

Invoice Product     Colour1     Colour2     Colour3
1       Pant        Red         Black
1       Shirt       Green
2       Pant        White       Black       Blue

这在SQL Server中是否可行?

2 个答案:

答案 0 :(得分:2)

在SQL Server中可以 - 如果您知道有三个颜色列。如果有一个变量号,那么它仍然可以,但它需要动态SQL。

我会使用条件聚合来解决这个问题:

select invoice, product,
       max(case when seqnum = 1 then colour end) as colour1,
       max(case when seqnum = 2 then colour end) as colour2,
       max(case when seqnum = 3 then colour end) as colour3
from (select t.*,
             row_number() over (partition by invoice, product order by (select nULL)) as seqnum
      from table t
     ) t
group by invoice, product;

答案 1 :(得分:0)

要将行转换为列,您需要在Pivot中使用Sql Server。如果您事先知道列数,则可以静态使用旋转作为 Gordin Linoff 建议的答案。

有时,colors的数量可能会有所不同(在您的示例中,只有3种颜色)。在这种情况下,您无法对列名进行硬编码。首先,您需要将列名称动态地转换为变量。

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + COLUMNNAME + ']', '[' + COLUMNNAME + ']')
               FROM    
               (
                     SELECT DISTINCT 
                     'COLOR'+CAST(ROW_NUMBER() OVER(PARTITION BY INVOICE,PRODUCT ORDER BY (SELECT 0)) AS VARCHAR(10)) COLUMNNAME
                     FROM #TEMP
               ) PV 
               ORDER BY COLUMNNAME

现在,上面的变量的列值为Comma Separated Values,可以与IN运算符动态地用于以下查询。由于您的表格没有COLOR1COLOR2等值,因此我提供了使用PARTITION BY获取每个INVOICE及其PRODUCT的列名的逻辑子句。

DECLARE @query NVARCHAR(MAX)
SET @query = '-- This outer query forms your pivoted result
             SELECT * FROM 
             (
                -- Source data for pivoting
                SELECT DISTINCT INVOICE,PRODUCT,COLOR,
                ''COLOR''+CAST(ROW_NUMBER() OVER(PARTITION BY INVOICE,PRODUCT ORDER BY (SELECT 0)) AS VARCHAR(10)) COLUMNNAME 
                FROM #TEMP                 
             ) x
             PIVOT 
             (
                 --Defines the values in each dynamic columns
                 MIN(COLOR)
                 -- Get the names from the @cols variable to show as column
                 FOR COLUMNNAME IN (' + @cols + ')
            ) p            
            ORDER BY INVOICE;' 

EXEC SP_EXECUTESQL @query