2016-08-05 48 views
0

Ich habe eine CSV-Datei mit 51 Spalten.Transpose Zeilen in Spalten SQL Server 2014

In dieser Reihenfolge gibt es eine UID-Spalte, eine serielle Spalte, eine Datumsspalte und 48 Spalten für jedes 30-Minuten-Segment des Tages (von 00:30 bis 00:00). Jeder Tag hat eine neue Zeile. So wie es aussieht:

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

ich diese Daten in 4 Spalten umsetzen müssen, so dass jede halbe Stunde eine UID, seriell und Datumsspalte hat. Mit anderen Worten, ich muss runter anstatt quer laufen.

Um wie folgt aussehen:

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

vielmehr, dass jeder Tag eine neue Zeile, wie es gegenwärtig der Fall ist, werde ich feststellen, dass Val_0130 zum Beispiel bestimmen, dass die Zeit 01.30 Uhr ist und mit dem Willen concat Datum

Ich habe versucht, mit Pivot und ohne Erfolg zu entfernen. Kann jemand den besten Ansatz empfehlen, dies zu tun?

+0

generieren Sie UID und seriell? Wenn ja, warum können Sie Ihr Datumsfeld nicht in dem von Ihnen gewünschten Intervall gruppieren und generieren? Aber, wenn UID und serial existieren, verleihen mir ihre Namen den Eindruck, dass sie einzigartig sind. Wie geht es Ihnen, ein distinct für Ihre 30-Minuten-Gruppierung zu wählen? – Kosch

+0

Die UID und Seriennummer werden vom Kunden zur Verfügung gestellt, um das Gerät zu identifizieren. Die UID ist eine Nummer, die das Gerät in einem Asset-Register findet und die Seriennummer ist nur die Seriennummer. Ich werde versuchen zu gruppieren und sehen, was passiert. –

+0

müssen Sie mit mehreren Instanzen von UID und seriell pro Zeitintervall Gruppe dann – Kosch

Antwort

2

Ich würde UNPIVOT verwenden und dann den Spaltennamen Val_0130 zerschneiden, um datetime hinzuzufügen, um das gewünschte Ergebnis zu erhalten. Auf diese Weise müssen Sie nur die 48 Spalten an einer Stelle schreiben.

hier einige Testdaten:

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) 

und die Abfrage

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 

Und wenn Sie wollen alle 48 Spalten nicht tippen, wie ich nicht wollen würde, nur Führen Sie diese Abfrage aus und kopieren Sie das Ergebnis in den Abschnitt ColumnNames IN() der obigen Abfrage.

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 
+0

Hallo Matt, das hat ein Vergnügen, was ist der Unterschied zwischen Pivot und Unpivot? –

+0

UNPIVOT ist, wenn Sie Spalten nehmen und sie Zeilen machen wollen, während PIVOT ist, wenn Sie Zeilen nehmen und sie Spalten machen möchten, so dass sie die umgekehrten sind. In Ihrem Fall hatten Sie einen Tisch, der bereits geschwenkt wurde, also wollten Sie ihn aufheben – Matt

1

Matt bietet eine gute Antwort mit UNPIVOT. Auf Plattformen, bei denen dies keine Option ist, können Sie den gleichen Effekt mit einem Cross-Join und einer Case-Anweisung erzielen. Erstellen Sie eine Tabelle von halben Stunden und produzieren Sie die Werte mit

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