2015-06-08 5 views
5

Supponiamo che io ho la seguente query inviata a BQ:Come pivot in Google BigQuery

SELECT shipmentID, category, quantity 
FROM [myDataset.myTable] 

Inoltre, si supponga che la query restituisce dati quali:

shipmentID category quantity 
1   shoes  5 
1   hats  3 
2   shirts 1 
2   hats  2 
3   toys  3 
2   books  1 
3   shirts 1 

Come posso ruotare i risultati , da BQ, per produrre output come segue:

shipmentID shoes hats shirts toys books 
1   5  3  0  0  0 
2   0  2  1  0  1 
3   0  0  1  3  0 

Come ulteriore sfondo, in realtà ho 2000+ ca le directory che ho bisogno di girare, e la quantità di dati è tale che non riesco a farlo direttamente attraverso un DataFrame di Pandas in Python (usa tutta la memoria, quindi rallenta a passo d'uomo). Ho provato a utilizzare un database relazionale, ma ho raggiunto un limite di colonne, quindi mi piacerebbe essere in grado di farlo direttamente in BQ, anche se devo costruire la query stessa tramite python. Eventuali suggerimenti?

** Modifica 1 Vorrei ricordare che la rotazione dei dati può essere eseguita in blocchi e quindi non è il problema. Il vero problema arriva nel tentativo di fare l'aggregazione in seguito, in modo da avere solo una riga per ogni ID spedizione. Questo è ciò che mangia tutta la RAM.

** Modifica 2 Dopo aver provato la risposta accettata di seguito, ho scoperto che provare a utilizzarlo per creare una tabella pivot di colonna 2k + causava errori "Risorse superate". Il mio team BQ è stato in grado di ridefinire la query per suddividerla in blocchi più piccoli e consentirne il passaggio. La struttura di base della query è la seguente:

SELECT 
    SetA.*, 
    SetB.*, 
    SetC.* 
FROM (
    SELECT 
    shipmentID, 
    SUM(IF (category="Rocks", qty, 0)), 
    SUM(IF (category="Paper", qty, 0)), 
    SUM(IF (category="Scissors", qty, 0)) 
    FROM (
    SELECT 
     a.shipmentid shipmentid, 
     a.quantity quantity, 
     a.category category 
    FROM 
     [myDataset.myTable] a) 
    GROUP EACH BY 
    shipmentID) SetA 
INNER JOIN EACH (
    SELECT 
    shipmentID, 
    SUM(IF (category="Jello Molds", quantity, 0)), 
    SUM(IF (category="Torque Wrenches", quantity, 0)) 
    FROM (
    SELECT 
     a.shipmentID shipmentID, 
     a.quantity quantity, 
     a.category category 
    FROM 
     [myDataset.myTable] a) 
    GROUP EACH BY 
    shipmentID) SetB 
ON 
    SetA.shipmentid = SetB.shipmentid 
INNER JOIN EACH (
    SELECT 
    shipmentID, 
    SUM(IF (category="Deep Thoughts", qty, 0)), 
    SUM(IF (category="Rainbows", qty, 0)), 
    SUM(IF (category="Ponies", qty, 0)) 
    FROM (
    SELECT 
     a.shipmentid shipmentid, 
     a.quantity quantity, 
     a.category category 
    FROM 
     [myDataset.myTable] a) 
    GROUP EACH BY 
    shipmentID) SetC 
ON 
    SetB.shipmentID = SetC.shipmentID 

il modello di cui sopra può essere continuato indefinitamente aggiungendo INNER JOIN EACH segmenti uno dopo l'altro. Per la mia applicazione, BQ era in grado di gestire circa 500 colonne per blocco.

+0

Hai dovuto digitare manualmente tutte le categorie? Mi sto imbattendo in un problema simile e sembra troppo lavoro. – Nivi

+0

Mi chiedo se hai provato a utilizzare i datafram PySpark per la rotazione? – Nivi

risposta

5

questo è un modo per farlo:

select shipmentID, 
    sum(IF (category='shoes', quantity, 0)) AS shoes, 
    sum(IF (category='hats', quantity, 0)) AS hats, 
    sum(IF (category='shirts', quantity, 0)) AS shirts, 
    sum(IF (category='toys', quantity, 0)) AS toys, 
    sum(IF (category='books', quantity, 0)) AS books, 
from 
    (select 1 as shipmentID,   'shoes' as category, 5 as quantity), 
    (select 1 as shipmentID,   'hats' as category,  3 as quantity), 
    (select 2 as shipmentID,   'shirts' as category, 1 as quantity), 
    (select 2 as shipmentID,   'hats' as category,  2 as quantity), 
    (select 3 as shipmentID,   'toys' as category,  3 as quantity), 
    (select 2 as shipmentID,   'books' as category,  1 as quantity), 
    (select 3 as shipmentID,   'shirts' as category, 1 as quantity), 
group by shipmentID 

Ciò restituisce:

+-----+------------+-------+------+--------+------+-------+---+ 
| Row | shipmentID | shoes | hats | shirts | toys | books | | 
+-----+------------+-------+------+--------+------+-------+---+ 
| 1 |   1 |  5 | 3 |  0 | 0 |  0 | | 
| 2 |   2 |  0 | 2 |  1 | 0 |  1 | | 
| 3 |   3 |  0 | 0 |  1 | 3 |  0 | | 
+-----+------------+-------+------+--------+------+-------+---+ 

consultare il manuale per altri pivot table example.

+0

sembra buono e dovrebbe essere relativamente facile creare la query in modo programmatico, dato un elenco di categorie. Darò un colpo. Grazie! :) – TraxusIV

+0

Provato questo, e funziona ... in parte. Cercando di eseguirlo su oltre 2000 categorie sfortunatamente produce "Risorse superate durante l'esecuzione". errore, ma funziona per un numero minore di categorie. – TraxusIV

+0

@TraxusIV puoi raggiungere il supporto di google o provare a pubblicare una nuova domanda con una query generata e menzionare un ID di lavoro non riuscito, qualcuno dal team di BQ sarà in grado di vedere se i limiti possono essere aumentati o meno. – Pentium10