将可变长度DB行展平为单个列

时间:2013-03-01 16:30:22

标签: sql sql-server sql-server-2005 pivot

我已经搜索过,无法找到完全符合我需求的解决方案,也找不到我可以修改的解决方案。我有一个数据库表,为简单起见,我们会说它有三列(packageIDcarriersequence)。对于任何包装,可以有一个或多个处理包装的承运人。我可以像

那样进行查询
SELECT packageID, carrier 
FROM packageFlow 
ORDER BY sequence

获取已处理包的所有人的列表:

packageID, carrier
1, Bob
1, Jim
1, Sally
1, Ron
2, Reggie
2, Mary
2, Bruce

我需要的是将结果分成如下行:

packageID|carrier1|carrier2|carrier3|carrier4
   1     |Bob     |Jim     |Sally   |Ron
   2     |Reggie  |Mary    |Bruce

Pivot似乎没有做我需要的东西,因为我没有聚合任何东西,我也无法让CTE正常工作。我很欣赏任何朝着正确方向的推动。

1 个答案:

答案 0 :(得分:3)

此数据转换为PIVOT。从SQL Server 2005开始,有一个函数可以将行转换为列。

如果您有一定数量的值,那么您可以对查询进行硬编码:

select *
from 
(
  select packageid, carrier,
    'Carrier_'+cast(row_number() over(partition by packageid order by packageid) as varchar(10)) col
  from packageflow
) src
pivot
(
  max(carrier)
  for col in (Carrier_1, Carrier_2, Carrier_3, Carrier_4)
) piv

请参阅SQL Fiddle with Demo

如果您要将未知数量的Carrier值转换为列,则可以使用动态sql:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(t.col) 
                    from 
                    (
                      select 'Carrier_'+cast(row_number() over(partition by packageid order by packageid) as varchar(10)) col
                      from packageFlow
                    ) t                    
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT packageid,' + @cols + ' from 
             (
                select packageid, carrier,
                  ''Carrier_''+cast(row_number() over(partition by packageid order by packageid) as varchar(10)) col
                from packageflow
            ) x
            pivot 
            (
                max(carrier)
                for col in (' + @cols + ')
            ) p '

execute(@query)

请参阅SQL Fiddle with Demo

注意:您将order by packageid替换为order by sequence

两个查询的结果是:

| PACKAGEID | CARRIER_1 | CARRIER_2 | CARRIER_3 | CARRIER_4 |
-------------------------------------------------------------
|         1 |       Bob |       Jim |     Sally |       Ron |
|         2 |    Reggie |      Mary |     Bruce |    (null) |