2016-06-14 21 views
5

Sto cercando di individuare il metodo ottimizzato per suddividere righe alternative di una colonna in due colonne. Mi spiego con un esempioDistribuisci i dati in due colonne

ho i seguenti dati

Source

Resultset voglio

Resultset

nell'esempio di cui sopra, la riga alternativa è spostato su una nuova colonna. Ho trovato una soluzione ma non è ottimizzata d se ho milioni di record.

mia soluzione (non ottimizzata)

;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 non funziona: ecco lo schema

CREATE TABLE tabA (
cola int 
); 


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

Sta dicendo il valore alternativa è sempre un numero negativo? E/o sempre inserito dopo il suo genitore? O che c'è una consistenza nel valore ABSOLUTE aumentato della colonna? O solo un esempio e postuli usando ROW_NUMBER() per risolverlo –

+0

@clifton_h no, potrebbe essere un valore positivo o negativo. Voglio solo il numero di riga 1,3,5,7 ... in una colonna e 2,4,6,8 ... in un altro –

+0

Quindi non c'è alcuna preoccupazione per l'ordine di pronunciare Col_Odd e Col_Even? –

risposta

4

Prova questa:

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 

uscita:

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

Funziona alla grande. Grazie, ma perché hai usato (ROW_NUMBER() OVER (ORDER BY (seleziona 1)) + 1)/2 AS rn, –

+0

@ankitsuhail L'ho usato per raggruppare le righe consecutive. Puoi usare un 'CTE' con' ROW_NUMBER' e poi consumare questo valore con la tabella derivata 'src'. Posso eseguire un po 'più veloce. –

+0

@Giogos Qualunque posto dove posso leggere sul comportamento di PIVOT come quello che sta succedendo qui?Come non mi ero mai imbattuto in una cosa così grande. –

2

si può fare con l'aggregazione condizionale, CASE EXPRESSION, ROUND e ABS, senza bisogno di funzioni finestra/rotazione:

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 

Ogni gruppo avrà un nuovo valore group_number che è il risultato assoluto del round di cola/100. Quindi si raggruppa e utilizza l'aggregazione condizionale per ruotarli.

+0

non è necessario che ogni numero alternativo non sia un numero negativo, anche se è colpa mia se ho fornito dati di questo tipo, ma una buona soluzione. Un'altra preoccupazione è che l'utilizzo di ABS, Round, Max, Min potrebbe degradare le prestazioni quando si parla di milioni di record. Perfavore, correggimi se sbaglio. –

+0

Credo che saranno più veloci allora 'ROW_NUMBER()', ma difficile da dire :) @ankitsuhail – sagi

+1

in realtà hai ragione su questo. Lo proverò con un tavolo enorme e posterò i risultati qui. –

1

Un altro modo con 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 

uscita:

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

perché una sinistra Unisciti? –

+0

Solo un'abitudine, in questo caso puoi usare INNER JOIN o LEFT JOIN o RIGHT JOIN. – gofr1

Problemi correlati