2016-06-14 11 views
5

Ich versuche herauszufinden, die am besten optimierte Möglichkeit, alternative Zeilen einer Spalte in zwei Spalten aufzuteilen. Lassen Sie mich das erklären durch ein BeispielVerteilen Sie Daten in zwei Spalten

Ich habe folgende Daten

Source

Resultset I

Resultset

im obigen Beispiel wollen, die alternative Zeile verschoben zu einer neuen Spalte. Ich habe eine Lösung gefunden, aber es ist nicht zu optimieren d wenn ich Millionen von Datensätzen habe.

Meine Lösung (nicht optimiert)

;WITH RecCtea 
AS 
(
SELECT *, ROW_NUMBER() OVER (ORDER BY (select 1)) rowid FROM tabA ta 
) 
SELECT a.cola,b.cola FROM (
(SELECT * FROM RecCtea rc WHERE rc.rowid%2 = 0) a JOIN 
(SELECT * from RecCtea rc2 where rc2.rowid%2 != 0) b 
on a.rowid = b.rowid+1 
) 

SQLfiddle ist nicht so, hier zu arbeiten ist das Schema

CREATE TABLE tabA (
cola int 
); 


INSERT tabA 
(
    cola 
) 
VALUES 
(100),(-100),(200),(-250),(300),(-350),(-400),(NULL) 
+0

Behaupten Sie, der alternative Wert immer eine negative Zahl ist? Und/oder immer nach seinem Elternteil eingefügt? Oder dass der erhöhte ABSOLUTE-Wert der Spalte konsistent ist? Oder nur ein Beispiel, und Sie postulieren mit ROW_NUMBER(), um es zu lösen –

+0

@ Clifton_h nein, es könnte ein positiver oder ein negativer Wert sein. Ich will nur Zeile Nummer 1,3,5,7 ... in einer Spalte und 2,4,6,8 ... in einem anderen –

+0

Also gibt es keine Sorge für die Reihenfolge von sagen Col_Odd und Col_Even? –

Antwort

4
diese

Versuchen:

SELECT [0] AS col1, [1] AS col2 
FROM 
(
    SELECT cola, 
     (ROW_NUMBER() OVER (ORDER BY (select 1)) + 1)/2 AS rn, 
     ROW_NUMBER() OVER (ORDER BY (select 1)) % 2 rowid 
    FROM tabA 
) AS src 
PIVOT (
    MAX(cola) FOR rowid IN ([0],[1])) AS pvt 

Ausgang:

col1 col2 
------+------ 
-100 | 100 
-250 | 200 
-350 | 300 
NULL | -400 
+0

Das funktioniert super. Danke, aber warum hast du (ROW_NUMBER() OVER (ORDER BY (wählen Sie 1)) + 1)/2 AS rn, –

+0

@ankitsuhail Ich habe es verwendet, um aufeinander folgende Reihen zu gruppieren. Sie können ein 'CTE' mit' ROW_NUMBER' verwenden und diesen Wert dann von der abgeleiteten Tabelle 'src' konsumieren. Ich kann etwas schneller arbeiten. –

+0

@Giogos Irgendein Ort, an dem ich über PIVOT-Verhalten lesen kann, was hier passiert?Da ich noch nie auf so eine tolle Sache gestoßen bin. –

2

Sie können es mit bedingten Aggregation tun, CASE EXPRESSION, ROUND und ABS, keine Notwendigkeit für Fensterfunktionen/Schwenken:

SELECT MAX(CASE WHEN t.cola < 0 THEN t.cola END) as cola_minus, 
     MAX(CASE WHEN t.cola > 0 THEN t.cola END) as cola_plus 
FROM (SELECT s.cola,ABS(ROUND(t.cola/100)) as group_number 
     FROM TabA s) t 
GROUP BY t.group_number 

Jede Gruppe wird eine neue bekommen Wert group_number das ist das absolute Ergebnis der Runde von cola/100. Dann wird es nach ihm gruppieren und die bedingte Aggregation verwenden, um sie zu pivotieren.

+0

ist es nicht notwendig, dass jede alternative Zahl keine negative Zahl sein wird, obwohl es mein Fehler ist, dass ich solche Daten aber nette Lösung gab. Ein weiteres Problem ist, dass die Verwendung von ABS, Round, Max und Min die Leistung beeinträchtigen kann, wenn wir über Millionen Datensätze sprechen. Bitte korrigieren Sie mich, wenn ich falsch liege. –

+0

Ich glaube, sie werden schneller als 'ROW_NUMBER()', aber schwer zu sagen :) @ankitsuhail – sagi

+1

eigentlich bist du hier richtig. Ich werde es mit einer riesigen Tabelle testen und die Ergebnisse hier veröffentlichen. –

1

Ein anderer Weg, mit CTE:

;WITH cte AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as rn, 
     cola 
FROM tabA 
) 

SELECT c2.cola, 
     c1.cola 
FROM cte c1 
LEFT JOIN cte c2 
    ON c1.rn = c2.rn-1 
WHERE c1.rn%2 = 1 AND c2.rn%2 = 0 

Ausgang:

cola cola 
-100 100 
-250 200 
-350 300 
NULL -400 
+0

Warum eine Linke Join? –

+0

Nur eine Angewohnheit, in diesem Fall können Sie INNER JOIN oder LEFT JOIN oder RIGHT JOIN verwenden. – gofr1

Verwandte Themen