将行转置为SQL Server 2014列

时间:2016-08-05 20:27:16

标签: sql pivot sql-server-2014

我有一个包含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但没有成功。任何人都可以建议最好的方法来做到这一点。

2 个答案:

答案 0 :(得分:2)

我会使用UNPIVOT,然后剪切列名Val_0130以添加到datetime以获得所需的结果。这样,您只需在一个位置写入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

答案 1 :(得分:1)

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

生成值
&  amp;