2013-09-25 10 views
12

Vorrei eseguire un'operazione DISTINCT su un sottoinsieme delle colonne. Il documentation dice che questo è possibile con un foreach nidificato:Come eseguire un DISTINCT in Pig Latin su un sottoinsieme di colonne?

Non è possibile utilizzare DISTINCT su un sottoinsieme di campi; per fare ciò, utilizzare FOREACH e un blocco nidificato per selezionare prima i campi e quindi applicare DISTINCT (vedere Esempio: Blocco nidificato).

È semplice da eseguire un'operazione DISTINCT su tutte le colonne:

A = LOAD 'data' AS (a1,a2,a3,a4); 
A_unique = DISTINCT A; 

Consente dire che sono interessati a condurre la distinta di tutti a1, a2, a3 e. Qualcuno può fornire un esempio che mostra come eseguire questa operazione con un foreach annidato come suggerito nella documentazione?

Ecco un esempio di ingresso e di uscita prevista:

A = LOAD 'data' AS(a1,a2,a3,a4); 
DUMP A; 

(1 2 3 4) 
(1 2 3 4) 
(1 2 3 5) 
(1 2 4 4) 

-- insert DISTINCT operation on a1,a2,a3 here: 
-- ... 

DUMP A_unique; 

(1 2 3 4) 
(1 2 4 4) 
+2

È possibile fornire un esempio di input e output previsti? – zero323

+0

Buon suggerimento, ho aggiornato la domanda. – Freerobots

risposta

18

Gruppo su tutte le altre colonne, progetto solo le colonne di interesse in un sacchetto, e quindi utilizzare FLATTEN per espandere loro di nuovo:

A_unique = 
    FOREACH (GROUP A BY a4) { 
     b = A.(a1,a2,a3); 
     s = DISTINCT b; 
     GENERATE FLATTEN(s), group AS a4; 
    }; 
+0

Esempio molto bello! Grazie per l'aiuto. Questo è molto simile alla mia risposta usando distinti, ma è molto più conciso. – Freerobots

+0

come possiamo abilitare la clausola parallela su di esso. Ho provato a utilizzare DEFAULT_PARALLEL 512 nel mio script ma questo non funziona e il numero di riduttori non è limitato a 512. Qualche raccomandazione? – TopCoder

0

Qui ci sono 2 soluzioni possibili, ci sono altri buoni approcci?

Soluzione 1 (con LIMIT 1):

A = LOAD 'test_data' AS (a1,a2,a3,a4); 

-- Combine the columns that I want to perform the distinct across into a tuple 
A2 = FOREACH A GENERATE TOTUPLE(a1,a2,a3) AS combined, a4 as a4 

-- Group by the combined column 
grouped_by_a4 = GROUP A2 BY combined; 

grouped_and_distinct = FOREACH grouped_by_a4 { 
     single = LIMIT A2 1; 
     GENERATE FLATTEN(single); 
}; 

Soluzione 2 (usando DISTINCT):

A = LOAD 'test_data' AS (a1,a2,a3,a4); 

-- Combine the columns that I want to perform the distinct across into a tuple 
A2 = FOREACH A GENERATE TOTUPLE(a1,a2,a3) AS combined, a4 as a4 

-- Group by the other columns (those I don't want the distinct applied to) 
grouped_by_a4 = GROUP A2 BY a4; 

-- Perform the distinct on a projection of combined and flatten 
grouped_and_distinct = FOREACH grouped_by_a4 { 
     combined_unique = DISTINCT A2.combined; 
     GENERATE FLATTEN(combined_unique); 
}; 
+0

Queste soluzioni non sono equivalenti. Il primo ti darà solo due tuple, poiché ci sono solo due combinazioni uniche di 'a1',' a2' e 'a3', e il valore di' a4' non è prevedibile. Il secondo darà un'uscita coerente con l'output del campione. (Non è così conciso come potrebbe essere, però.) –

1

per la vostra specificato input/output, il seguente funziona. Potresti aggiornare i tuoi vettori di test per chiarire che cosa ti serve che sia diverso da questo.

A_unique = DISTINCT A; 
+0

Sì, questo potrebbe aiutare :). Ho aggiornato l'output previsto nella domanda originale. – Freerobots

2

La risposta accettata è una grande soluzione, ma, nel caso in cui si desidera riordinare i campi nella uscita (cosa che ho dovuto fare di recente) questo potrebbe non funzionare. Ecco un'alternativa:

A = LOAD '$input' AS (f1, f2, f3, f4, f5); 
GP = GROUP A BY (f1, f2, f3); 
OUTPUT = FOREACH GP GENERATE 
    group.f1, group.f2, f4, f5, group.f3 ; 

Quando gruppo su alcuni campi, la selezione dovrebbe avere valori univoci per il gruppo in un ogni tupla.

0
unique_A = FOREACH (GROUP A BY (a1, a2, a3)) { 
    limit_a = LIMIT A 1; 
    GENERATE FLATTEN(limit_a) AS (a1,a2,a3,a4); 
}; 
Problemi correlati