2013-09-25 17 views
12

Chciałbym wykonać operację DISTINCT na podzbiorze kolumn. documentation mówi, że jest to możliwe z zagnieżdżonym foreach:Jak wykonać DISTINCT w Pig Latin w podzbiorze kolumn?

Nie można użyć DISTINCT na podzestawie pól; w tym celu użyj FOREACH i zagnieżdżonego bloku, aby najpierw wybrać pola, a następnie zastosować DISTINCT (patrz Przykład: Zagnieżdżony blok).

To jest proste do wykonania odrębną operację na wszystkich kolumnach:

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

Powiedzmy, że jestem zainteresowany wykonaniem odrębny całej A1, A2 i A3. Czy ktoś może podać przykład pokazujący, jak wykonać tę operację z zagnieżdżonym foreach, jak sugeruje dokumentacja?

Oto przykład wejścia i oczekiwany wynik:

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

Czy możesz podać przykładowy sygnał wejściowy i oczekiwany wynik? – zero323

+0

Dobra sugestia, zaktualizowałem pytanie. – Freerobots

Odpowiedz

18

Grupa na wszystkich innych kolumn, projekt tylko kolumny to w torbie, a następnie użyć FLATTEN rozszerzyć je ponownie:

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

Bardzo ładny przykład! Dzięki za pomoc. Jest to bardzo podobne do mojej odpowiedzi przy użyciu różnych, ale jest znacznie bardziej zwięzłe. – Freerobots

+0

jak możemy włączyć na nim klauzulę równoległą. Próbowałem używać DEFAULT_PARALLEL 512 w moim skrypcie, ale to nie działa i # z reduktorów nie jest ograniczone do 512. Jakieś rekomendacje? – TopCoder

0

Oto 2 możliwe rozwiązania, czy są jakieś inne dobre podejście?

Rozwiązanie 1 (przy użyciu 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); 
}; 

Rozwiązanie 2 (przy użyciu 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

Te rozwiązania nie są równoważne. Ten pierwszy da ci tylko dwie krotki, ponieważ istnieją tylko dwie unikalne kombinacje "a1", "a2" i "a3", a wartość dla "a4" jest nieprzewidywalna. Drugi da dane wyjściowe zgodne z wynikami twojej próbki. (To nie jest tak zwięzłe, jak mogłoby się wydawać.) –

1

określonej przez Ciebie wejście/wyjście, następujące prace. Możesz zaktualizować swoje wektory testowe, aby wyjaśnić, czego potrzebujesz, co jest inne niż to.

A_unique = DISTINCT A; 
+0

Tak, to może pomóc :). Zaktualizowałem oczekiwany wynik w pierwotnym pytaniu. – Freerobots

2

Zaakceptowanych odpowiedź jest doskonałym rozwiązaniem, ale w przypadku, gdy chcesz zmienić kolejność pól w wyjściu (coś musiałem zrobić niedawno) to może nie działać. Oto alternatywa:

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 ; 

Podczas grupowania na niektórych polach wybór będzie miał unikalne wartości dla grupy w każdej krotce.

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