【问题标题】:Transpose rows into columns SQL Server 2014将行转换为列 SQL Server 2014
【发布时间】:2016-08-05 20:27:16
【问题描述】:

我有一个包含 51 列的 CSV 文件。

按此顺序,一天中的每个 30 分钟段(从 00:30 到 00:00)有一个 UID 列、序列列、日期列和 48 个列。每天都有新的一行。 所以它看起来像:

UID | Serial | Date       | Val_0030 | Val_0100 | Val_0130 | ..... | Val_0000
123 | 123456 | 2016-01-02 | 56.2     | 23.25    | 32.8     | ..... | 86.23

我需要将这些数据转换成 4 列,这样每半小时就有一个 UID、Serial 和 Date 列。换句话说,我需要跑下来而不是穿过。

看起来像这样:

UID | Serial | 2016-01-02 00:30 | Value

而不是像现在这样每天都有一个新行,我将确定 Val_0130 例如将确定时间为 01:30 并将与日期连接

我曾尝试使用 pivot 和 unpivot,但没有成功。谁能建议最好的方法来做到这一点。

【问题讨论】:

  • 你在生成 UID 和序列号吗?如果是这样,为什么您不能按您需要的时间间隔对日期字段进行分组并生成它们?但是,如果 UID 和序列号存在,它们的名字让我认为它们是独一无二的......你如何为你的 30 分钟分组选择一个不同的?
  • UID和序列号由客户提供,用于识别设备。 UID 是在资产登记簿中定位设备的编号,序列号就是序列号。我会尝试分组,看看会发生什么。
  • 您需要处理每个时间间隔组的多个 UID 和序列实例
  • 或者如果您需要该详细信息,您可以将它们包含在您的分组中,但是您将多次出现相同的 30 分钟间隔。基本上按设备

标签: sql pivot sql-server-2014


【解决方案1】:

我会使用UNPIVOT,然后剪切列名Val_0130 以添加到日期时间以获得所需的结果。这样,您只需将 48 列写在一个位置。

这是一些测试数据:

DECLARE @Table AS TABLE (UID INT, Serial INT, Date DATETIME, Val_0030 MONEY, Val_0100 MONEY, Val_0130 MONEY, Val_0000 MONEY)
INSERT INTO @Table (UID, Serial, Date, Val_0030, Val_0100, Val_0130, Val_0000)
VALUES
(123, 123456, '2016-01-02',56.2,23.25,12.34,86.23)
,(231, 234561, '2016-01-05',26.2,13.25,23.45,106.23)
,(312, 345612, '2016-01-07',76.2,3.25,34.56,1010.56)

还有查询

SELECT
    UID
    ,Serial
    ,DateWithTime = [Date] + CAST((SUBSTRING(ColumnNames,5,2) + ':' + RIGHT(ColumnNames,2)) AS DATETIME)
    ,Value
FROM
    @Table t
    UNPIVOT (
       Value
       FOR ColumnNames IN (Val_0030, VAL_0100, Val_0130, VAL_0000)
    ) u

如果您不想输入所有 48 列,就像我不想那样,只需运行此查询并将结果复制并粘贴到上述查询的 ColumnNames IN () 部分。

DECLARE @ColString VARCHAR(MAX) = ''
DECLARE @DT DATETIME = '00:00'

WHILE @DT < '1900-01-02 00:00:00.000'
BEGIN
    IF LEN(@ColString) > 0
    BEGIN
       SET @ColString += ','
    END

    SET @ColString += 'Val_' + FORMAT(@DT,'HHmm')

    SET @DT = DATEADD(MINUTE,30,@DT)
END

SELECT @ColString

【讨论】:

  • 嗨,Matt,这很奏效,pivot 和 unpivot 有什么区别?
  • UNPIVOT 是当您想要获取列并将它们设为行时,而 PIVOT 用于当您想要获取行并将它们设为列时,它们彼此相反。在您的情况下,您有一个已经旋转的表格,因此您想取消旋转它
【解决方案2】:

Matt 通过 UNPIVOT 提供了一个很好的答案。在无法选择的平台上,您可以使用交叉连接和 case 语句获得相同的效果。创建一个半小时表,并使用

生成值
select ...
       , case hh.time  when '00:00' then VAL_0000
                       when '00:30' then Val_0030
                       when '01:00' then Val_0100
                       when '01:30' then Val_0130
         ...
         end as Value
from data cross join "half-hours" as hh

【讨论】:

    猜你喜欢
    • 2021-01-30
    • 2021-02-24
    • 2010-10-22
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多