【问题标题】:SQL Server- PIVOT table. transform row into columnsSQL Server- PIVOT 表。将行转换为列
【发布时间】:2012-12-04 16:55:37
【问题描述】:

我正在尝试将行转换为列。这是我的查询

SELECT M.urn,
       M.eventdate,
       M.eventlocation,
       M.eventroom,
       M.eventbed,
       N.time
FROM   admpatevents M
       INNER JOIN admpattransferindex N
               ON M.urn = N.urn
                  AND M.eventseqno = N.eventseqno
                  AND M.eventdate = N.eventdate
WHERE  M.urn = 'F1002754364'
       AND M.eventcode = 'TFRADMIN'

当前结果

URN 日期 地点 房间 床位 时间
F1002754364 20121101 EDEXPRESS 4-152 02 0724
F1002754364 20121101 CARDSURG 3-110 02 1455
F1002754364 20121102 胸部单元 6-129-GL04 1757

要求的结果

F1002754364 20121101 EDEXPRESS 4-152 02 0724 20121101 CARDSURG 3-110 02 1455 20121102 胸部单元 6-129-GL 04 1757

感谢您的帮助。

【问题讨论】:

    标签: sql sql-server tsql pivot


    【解决方案1】:

    由于您使用的是 SQL Server,因此您可以同时使用 UNPIVOTPIVOT 函数来转换此数据。如果您知道您将拥有多少个值,那么您可以对这些值进行硬编码,如下所示:

    select *
    from
    (
        select urn,
            value,
            col +'_'+ CAST(rn as varchar(10)) as col
        from 
        (
            SELECT M.urn,
                cast(M.eventdate as varchar(50)) eventdate,
                M.eventlocation,
                M.eventroom,
                M.eventbed,
                cast(N.time as varchar(50)) time,
                ROW_NUMBER() over(PARTITION by m.urn order by m.eventdate) rn
            FROM   admpatevents M
            INNER JOIN admpattransferindex N
                ON M.urn = N.urn
                AND M.eventseqno = N.eventseqno
                AND M.eventdate = N.eventdate
            WHERE  M.urn = 'F1002754364'
                AND M.eventcode = 'TFRADMIN'
        ) src1
        unpivot
        (
            value 
            for col in (eventdate, eventlocation, eventroom, eventbed, time)
        ) unpiv
    ) src2
    pivot
    (
        max(value)
        for col in ([eventdate_1], [eventlocation_1], [eventroom_1], [eventbed_1], [time_1],
                    [eventdate_2], [eventlocation_2], [eventroom_2], [eventbed_2], [time_2],
                    [eventdate_3], [eventlocation_3], [eventroom_3], [eventbed_3], [time_3])
    ) piv
    

    注意-未测试

    如果你有未知数量的列,那么你可以使用类似这样的动态 sql:

    DECLARE  @query  AS NVARCHAR(MAX),
        @colsPivot as  NVARCHAR(MAX)
    
    select @colsPivot = STUFF((SELECT  ',' 
                          + quotename(c.name +'_'+ cast(t.rn as varchar(10)))
                        from
                        (
                            select ROW_NUMBER() over(PARTITION by m.urn order by m.eventdate) rn
                            FROM   admpatevents M
                            INNER JOIN admpattransferindex N
                                ON M.urn = N.urn
                                AND M.eventseqno = N.eventseqno
                                AND M.eventdate = N.eventdate
                            WHERE  M.urn = 'F1002754364'
    
                        ) t
                        cross apply sys.columns as C
                       where C.object_id IN (object_id('admpatevents'), object_id('admpattransferindex')) and
                             C.name not in ('urn') -- add any other columns your want to exclude
                       group by c.name, t.rn
                       order by t.rn
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    
    set @query 
      = 'select *
         from
         (
           select urn, value, col +''_''+ CAST(rn as varchar(10)) as col
           from
           (
                SELECT M.urn,
                    cast(M.eventdate as varchar(20)) eventdate,
                    M.eventlocation,
                    M.eventroom,
                    M.eventbed,
                    cast(N.time as varchar(20)) time,
                    ROW_NUMBER() over(PARTITION by m.urn order by m.eventdate) rn
                FROM   admpatevents M
                INNER JOIN admpattransferindex N
                    ON M.urn = N.urn
                    AND M.eventseqno = N.EVENTseqno
                    AND M.eventdate = N.eventdate
                WHERE  M.urn = ''F1002754364''
    
           ) x
           unpivot
           (
             value
             for col in (eventdate, eventlocation, eventroom, eventbed, time)
           ) u
          ) x1
          pivot
          (
            max(value)
            for col in ('+ @colspivot +')
          ) p'
    
    exec(@query)
    

    SQL Fiddle with Demo

    【讨论】:

    • 感谢您的帮助。运行这两个语句时出现错误。第一条语句错误:“eventlocation”列的类型与UNPIVOT列表中指定的其他列的类型冲突。第二条语句错误:消息 156,级别 15,状态 1,第 7 行关键字“SELECT”附近的语法不正确。消息 102,级别 15,状态 1,第 21 行 ')' 附近的语法不正确。再次感谢
    • @Matt 所有未透视的列的数据类型必须相同。因此,您必须执行类似于我为 eventdate 所做的转换。如果您愿意,请使用您的表格和一些示例数据创建一个sql fiddle,以便我进行测试。 :)
    • 第一个语句在您提到的更改数据类型后起作用。第二个语句,有一些小问题,如 ')' 。我试图改变')'但没有奏效。让我在 SQL 小提琴中创建模式。我会告诉你。谢谢
    • @Matt 看到我的编辑,它现在正在处理这个演示 -- sqlfiddle.com/#!3/6c1cd/16
    猜你喜欢
    • 2013-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多