1

是否有 T-SQL (SQL Server 2008R2) 查询转换TABLE_1为预期的结果集?

表格1

+----------+-------------------------+---------+------+
| IdDevice | Timestamp               | M300    | M400 |
+----------+-------------------------+---------+------+
| 3        | 2012-12-05 16:29:51.000 | 2357,69 | 520  |
| 6        | 2012-12-05 16:29:51.000 | 1694,81 | 470  |
| 1        | 2012-12-05 16:29:51.000 | 2046,33 | 111  |
+----------+-------------------------+---------+------+

预期结果集

+-------------------------+---------+--------+---------+--------+---------+--------+
|        Timestamp        | 3_M300  | 3_M400 | 6_M300  | 6_M400 | 6_M300  | 6_M400 |
+-------------------------+---------+--------+---------+--------+---------+--------+
| 2012-12-05 16:29:51.000 | 2357,69 |    520 | 1694,81 |    470 | 2046,33 |    111 |
+-------------------------+---------+--------+---------+--------+---------+--------+
4

1 回答 1

2

这仍然是一个PIVOT查询,但在PIVOT您必须执行UNPIVOT您的列之前。

首先,您执行将UNPIVOT当前的多列转换为两列 - 一个带有值,另一个带有列名。的关键UNPIVOT是数据类型相同,因此在子查询中,我将cast任何列指向相同的数据类型:

select timestamp,
    value, cast(iddevice as varchar(10)) + '_'+col as col
  from
  (
    select iddevice,
      timestamp,
      cast(m300 as varchar(10)) m300,
      cast(m400 as varchar(10)) m400
    from yourtable
  ) src
  unpivot
  (
    value
    for col in (m300, m400)
  ) unpiv

请参阅带有演示的 SQL Fiddle

结果:

|                       TIMESTAMP |   VALUE |    COL |
------------------------------------------------------
| December, 05 2012 16:29:51+0000 | 2357,69 | 3_m300 |
| December, 05 2012 16:29:51+0000 |     520 | 3_m400 |
| December, 05 2012 16:29:51+0000 | 1694,81 | 6_m300 |
| December, 05 2012 16:29:51+0000 |     470 | 6_m400 |
| December, 05 2012 16:29:51+0000 | 2046,33 | 1_m300 |
| December, 05 2012 16:29:51+0000 |     111 | 1_m400 |

完成 unpivot 后,您可以应用该PIVOT功能:

select *
from
(
  select timestamp,
    value, cast(iddevice as varchar(10)) + '_'+col as col
  from
  (
    select iddevice,
      timestamp,
      cast(m300 as varchar(10)) m300,
      cast(m400 as varchar(10)) m400
    from yourtable
  ) src
  unpivot
  (
    value
    for col in (m300, m400)
  ) unpiv
) src1
pivot
(
  max(value)
  for col in ([3_m300], [3_m400],
              [6_m300], [6_m400],
              [1_m300], [1_m400])
) piv

请参阅带有演示的 SQL Fiddle

结果:

|                       TIMESTAMP |  3_M300 | 3_M400 |  6_M300 | 6_M400 |  1_M300 | 1_M400 |
--------------------------------------------------------------------------------------------
| December, 05 2012 16:29:51+0000 | 2357,69 |    520 | 1694,81 |    470 | 2046,33 |    111 |

IdDevices如果您想要转换成列的数量未知,那么您可以使用动态 SQL:

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

select @cols = STUFF((SELECT DISTINCT ',' 
                      + quotename(cast(t.IdDevice as varchar(10)) +'_'
                                  +c.name)
                    from yourtable t
                     cross apply sys.columns as C
                   where C.object_id = object_id('yourtable') and
                         C.name not in ('IdDevice', 'Timestamp')
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT timestamp,' + @cols + ' from 
             (
               select timestamp,
                value, cast(iddevice as varchar(10)) + ''_''+col as col
              from
              (
                select iddevice,
                  timestamp,
                  cast(m300 as varchar(10)) m300,
                  cast(m400 as varchar(10)) m400
                from yourtable
              ) src
              unpivot
              (
                value
                for col in (m300, m400)
              ) unpiv
            ) x
            pivot
            (
              max(value)
              for col in (' + @cols + ')
            ) p '

execute(@query)

请参阅带有演示的 SQL Fiddle

编辑,如果您需要每个 m 值的总计字段,那么您可以使用:

select timestamp,
  [3_m300], [3_m400],
  [6_m300], [6_m400],
  [1_m300], [1_m400],
  [1_m300] + [3_m300] + [6_m300] Total_m300,
  [1_m400] + [3_m400] + [6_m400] Total_m400
from
(
  select timestamp,
    value, cast(iddevice as varchar(10)) + '_'+col as col
  from
  (
    select iddevice,
      timestamp,
      m300,
      m400
    from yourtable
  ) src
  unpivot
  (
    value
    for col in (m300, m400)
  ) unpiv
) src1
pivot
(
  sum(value)
  for col in ([3_m300], [3_m400],
              [6_m300], [6_m400],
              [1_m300], [1_m400])
) piv

请参阅带有演示的 SQL Fiddle

于 2012-12-05T16:50:46.253 回答