2009-07-15 12 views
18

Esiste una funzione equivalente non pivot in PostgreSQL?unpivot e PostgreSQL

+0

Sarebbe bello se si spiega che cosa è "unipivot". –

+0

@Milen A. Radev: In PostgreSQL, come riportato da @Bill Karwin, la funzione crosstab() viene utilizzata per le operazioni di pivot.Il documento dice: "La funzione della tabella a campi incrociati viene utilizzata per produrre visualizzazioni" pivot ", in cui i dati sono elencati in tutta la pagina anziché in basso." Quindi, unpivot, presumo che @Tony Searle significhi "i dati sono elencati nella pagina, piuttosto che attraverso". Vedi la mia risposta qui sotto. – Stew

risposta

61

Creare una tabella di esempio:

CREATE TEMP TABLE foo (id int, a text, b text, c text); 
INSERT INTO foo VALUES (1, 'ant', 'cat', 'chimp'), (2, 'grape', 'mint', 'basil'); 

Si puo 'UNPIVOT' o 'uncrosstab' utilizzando UNION ALL:

SELECT id, 
     'a' AS colname, 
     a AS thing 
FROM foo 
UNION ALL 
SELECT id, 
     'b' AS colname, 
     b AS thing 
FROM foo 
UNION ALL 
SELECT id, 
     'c' AS colname, 
     c AS thing 
FROM foo 
ORDER BY id; 

Questo esegue 3 subquery diverse su foo, una per e ach colonna vogliamo unpivot e restituisce, in una tabella, ogni record di ciascuna subquery.

Ma questo eseguirà la scansione della tabella N volte, dove N è il numero di colonne che si desidera annullare. Questo è inefficiente e un grosso problema quando, ad esempio, si sta lavorando con una tabella molto grande che richiede molto tempo per la scansione.

Invece, l'uso:

SELECT id, 
     unnest(array['a', 'b', 'c']) AS colname, 
     unnest(array[a, b, c]) AS thing 
FROM foo 
ORDER BY id; 

Questo è più facile da scrivere, e sarà solo la scansione della tabella una volta.

array[a, b, c] restituisce un oggetto array, con i valori di a, b, e c come elementi. unnest(array[a, b, c]) interrompe i risultati in una riga per ciascuno degli elementi dell'array.

Spero che questo aiuti!

+1

La strategia 'unnest' è molto utile ed efficiente su grandi tabelle con 255 colonne, grazie! –

+4

C'è un'altra soluzione che usa il modulo 'hstore' descritto in questo blog: http://www.postgresonline.com/journal/archives/283-Unpivoting-data-in-PostgreSQL.html –

4

FYI per quelli di noi che cercano come unpivot in RedShift.

La soluzione di forma lunga data da Stew sembra essere l'unico modo per ottenere questo risultato.

https://forums.aws.amazon.com/thread.jspa?threadID=126369


Per coloro che non possono vedere lì ecco il testo incollato sotto ...

Non abbiamo le funzioni built-in che farà perno o UNPIVOT. Tuttavia, puoi sempre scrivere SQL per farlo.

create table sales (regionid integer, q1 integer, q2 integer, q3 integer, q4 integer); 
insert into sales values (1,10,12,14,16), (2,20,22,24,26); 

select * from sales order by regionid; 

regionid | q1 | q2 | q3 | q4 
----------+----+----+----+---- 
1 | 10 | 12 | 14 | 16 
2 | 20 | 22 | 24 | 26 

(2 rows) 

interrogazione perno

create table sales_pivoted (regionid, quarter, sales) 
as 
select regionid, 'Q1', q1 from sales 
UNION ALL 
select regionid, 'Q2', q2 from sales 
UNION ALL 
select regionid, 'Q3', q3 from sales 
UNION ALL 
select regionid, 'Q4', q4 from sales 
; 

select * from sales_pivoted order by regionid, quarter; 

regionid | quarter | sales 
----------+---------+------- 
1 | Q1 | 10 
1 | Q2 | 12 
1 | Q3 | 14 
1 | Q4 | 16 
2 | Q1 | 20 
2 | Q2 | 22 
2 | Q3 | 24 
2 | Q4 | 26 
(8 rows) 

interrogazione UNPIVOT

select regionid, sum(Q1) as Q1, sum(Q2) as Q2, sum(Q3) as Q3, sum(Q4) as Q4 
from 
(select regionid, 
case quarter when 'Q1' then sales else 0 end as Q1, 
case quarter when 'Q2' then sales else 0 end as Q2, 
case quarter when 'Q3' then sales else 0 end as Q3, 
case quarter when 'Q4' then sales else 0 end as Q4 
from sales_pivoted) 

group by regionid 
order by regionid; 
regionid | q1 | q2 | q3 | q4 
----------+----+----+----+---- 
1 | 10 | 12 | 14 | 16 
2 | 20 | 22 | 24 | 26 
(2 rows) 

Spero che questo aiuti, Neil