是否有可能像这样透视数据?

时间:2013-10-15 19:31:21

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

我的数据如下:

enter image description here

我想调整这些数据,以便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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

根据评论中的要求加入两个数据透视表的示例。

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

答案 2 :(得分:1)

您可以使用PIVOT函数获取结果,但必须将多列中的LineageReadTime列拆分为多行。

由于您使用的是SQL Server 2012,因此可以使用CROSS APPLY和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 |