【问题标题】:Flatten variable length DB rows into a single column将可变长度 DB 行展平为单列
【发布时间】:2013-02-16 05:26:23
【问题描述】:

我已经搜索并找不到完全符合我需求的解决方案,也找不到我可以修改的解决方案。我有一个数据库表,为简单起见,我们会说它有三列(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 正常工作。我会很感激任何朝着正确方向的推动。

【问题讨论】:

  • 您应该告诉我们您使用的是什么 RDBMS。 Oracle LEAD 可以帮助解决这类问题。
  • 您尚未指定 DBMS,但this answer 为大多数 DMBS 提供了解决方案。
  • 您希望将数据连接到单个列中吗?还是您想要单独的列?
  • 以上引用的两个帖子都是为了将​​它们连接成一个列,我已经知道该怎么做。我需要多列。我更新了我的帖子以更清晰。

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


【解决方案1】:

此数据转换为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) |

【讨论】:

  • 太棒了!!谢谢,我太专注于使用数据透视表的聚合部分,无法通过它。
  • @dsvick 我很高兴你能成功,总是乐于提供帮助! :)
猜你喜欢
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
相关资源
最近更新 更多