【问题标题】:Is it possible to Pivot data like this?是否可以像这样透视数据?
【发布时间】:2013-10-23 17:53:37
【问题描述】:

我的数据如下所示:

我想转置这些数据,以便 SubId 只有一行。列将是 SubId、802Lineage、802ReadTime、1000Lineage、1000ReadTime 等。

如果不需要包含 Lineage,这将非常简单,如下所示:

Select SubId, [800] as [800Time], [1190] as [1190Time], [1605] as [1605Time]
From
(Select SubId, ProcessNumber, ReadTime From MyTable) as SourceTable
PIVOT
(
    Max(ReadTime)
    For ProcessNumber IN ([800],[802],[1190],[1605])
) as PivotTable;

我只是不确定如何使用包含的 Lineage 来执行此操作。这是针对 SQL Server 2012 的

【问题讨论】:

  • 为什么不在 SubId 上加入两个枢轴?
  • 你能举个例子吗?

标签: sql sql-server tsql sql-server-2012 pivot


【解决方案1】:

您可以手动旋转:

select
    SubId,
    max(case when ProcessNumber = 802 then ReadTime end) as [802Time],
    max(case when ProcessNumber = 802 then Lineage end) as [802Lineage],
    ....
from SourceTable
group by SubId

【讨论】:

  • 嗯...有趣的想法。谢谢。
  • @RandyMinder 这种枢轴非常灵活,你可以混合不同的聚合,如果你喜欢。它确实需要更多的代码,但对我来说,未来扩展比标准枢轴要容易得多
【解决方案2】:

按照 cmets 的要求连接两个数据透视表的示例。

CREATE TABLE #MyTable (SubId int, ProcessNumber int, Lineage varchar(16), ReadTime datetime)
INSERT INTO #MyTable 
        (SubID, ProcessNumber, Lineage, ReadTime)
VALUES
        (1, 9, 'A', GETDATE()),
        (1, 8, 'A', GETDATE()),
        (1, 7, 'B', GETDATE()),
        (2, 9, 'C', GETDATE()),
        (2, 8, 'C', GETDATE())
SELECT * 
FROM (
   Select SubId, [9] as [9Time], [8] as [8Time], [7] as [7Time]
   From
   (Select SubId, ProcessNumber, ReadTime From #MyTable) as SourceTable
   PIVOT(Max(ReadTime) For ProcessNumber IN ([9],[8],[7],[6])) as PivotTable1
) AS T1
INNER JOIN (
   Select SubId, [9] as [9Lineage], [8] as [8Lineage], [7] as [7Lineage]
   From
   (Select SubId, ProcessNumber, Lineage From #MyTable) as SourceTable
   PIVOT(Max(Lineage) For ProcessNumber IN ([9],[8],[7],[6])) as PivotTable1
 ) AS T2
ON T1.SubId = T2.SubId
GO

【讨论】:

    【解决方案3】:

    您可以使用 PIVOT 函数来获取结果,但您必须将 LineageReadTime 列从多列取消旋转为多行。

    由于您使用的是 SQL Server 2012,因此您可以使用 CROSS APPLY with VALUES 对数据进行反透视:

    select subid, 
      colname = cast(processNumber as varchar(10)) + colname,
      value
    from mytable
    cross apply
    (
      values
        ('Lineage', Lineage),
        ('ReadTime', convert(varchar(20), readtime, 120))
    ) c (colname, value)
    

    SQL Fiddle with Demo。这会将您当前的数据转换为以下格式:

    |       SUBID |      COLNAME |               VALUE |
    |-------------|--------------|---------------------|
    | 12010231146 |   802Lineage |              PBG12A |
    | 12010231146 |  802ReadTime | 2012-01-02 21:44:00 |
    | 12010231146 |  1000Lineage |              PBG12A |
    | 12010231146 | 1000ReadTime | 2012-01-02 21:43:00 |
    | 12010231146 |  1190Lineage |              PBG11B |
    | 12010231146 | 1190ReadTime | 2012-01-03 14:36:00 |
    

    一旦数据采用这种格式,您就可以轻松地应用 PIVOT 函数来获得最终结果:

    select *
    from
    (
      select subid, 
        colname = cast(processNumber as varchar(10)) + colname,
        value
      from mytable
      cross apply
      (
        values
          ('Lineage', Lineage),
          ('ReadTime', convert(varchar(20), readtime, 120))
      ) c (colname, value)
    ) d
    pivot
    (
      max(value)
      for colname in ([802Lineage], [802ReadTime],
                      [1000Lineage], [1000ReadTime],
                      [1190Lineage], [1190ReadTime])
    ) piv;
    

    SQL Fiddle with Demo

    如果您想要转换的行数有限,上述方法非常有用,但如果您有一个未知数,那么您可以使用动态 SQL:

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT ',' + QUOTENAME(cast(processnumber as varchar(10))+col) 
                        from mytable
                        cross apply
                        (
                          select 'Lineage', 0 union all
                          select 'ReadTime', 1
                        ) c (col, so)
                        group by processnumber, col, so
                        order by processnumber, so
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    
    set @query = 'SELECT subid, ' + @cols + ' 
                from 
                (
                  select subid, 
                    colname = cast(processNumber as varchar(10)) + colname,
                    value
                  from mytable
                  cross apply
                  (
                    values
                      (''Lineage'', Lineage),
                      (''ReadTime'', convert(varchar(20), readtime, 120))
                  ) c (colname, value)
                ) x
                pivot 
                (
                    max(value)
                    for colname in (' + @cols + ')
                ) p '
    
    execute sp_executesql @query;
    

    SQL Fiddle with Demo。这给出了一个结果:

    |       SUBID | 802LINEAGE |         802READTIME | 1000LINEAGE |        1000READTIME | 1190LINEAGE |        1190READTIME | 1605LINEAGE |        1605READTIME | 1745LINEAGE |        1745READTIME | 1790LINEAGE |        1790READTIME | 1990LINEAGE |        1990READTIME | 2690LINEAGE |        2690READTIME | 2795LINEAGE |        2795READTIME | 2990LINEAGE |        2990READTIME | 3090LINEAGE |        3090READTIME | 3290LINEAGE |        3290READTIME |
    |-------------|------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|-------------|---------------------|
    | 12010231146 |     PBG12A | 2012-01-02 21:44:00 |      PBG12A | 2012-01-02 21:43:00 |      PBG11B | 2012-01-03 14:36:00 |      PBG11B | 2012-01-03 15:15:00 |      PBG11A | 2012-01-03 15:16:00 |      PBG11A | 2012-01-03 15:19:00 |      PBG11A | 2012-01-03 15:23:00 |      PBG11A | 2012-01-03 15:32:00 |      PBG11A | 2012-01-03 15:39:00 |      PBG11A | 2012-01-03 15:41:00 |      PBG11A | 2012-01-03 15:46:00 |      PBG11A | 2012-01-03 15:47:00 |
    

    【讨论】:

      猜你喜欢
      • 2022-01-03
      • 2021-05-13
      • 2013-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      相关资源
      最近更新 更多