Как выполнить DISTINCT в Pig Latin на подмножестве столбцов?

Я хотел бы выполнить операцию DISTINCT для подмножества столбцов. В документации говорится, что это возможно с помощью вложенного foreach:

Вы не можете использовать DISTINCT для подмножества полей; для этого используйте FOREACH и вложенный блок, чтобы сначала выбрать поля, а затем применить DISTINCT (см. Пример: Вложенный блок).

Проще всего выполнить операцию DISTINCT для всех столбцов:

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

Давайте скажем, что меня интересует выполнение отдельных элементов через a1, a2 и a3. Может ли кто-нибудь представить пример, показывающий, как выполнить эту операцию с вложенным foreach, как это предлагается в документации?

Здесь приведен пример ввода и ожидаемого вывода:

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)

Ответ 1

Группируйте все остальные столбцы, проецируйте только интересующие столбцы в сумку, а затем используйте FLATTEN, чтобы развернуть их снова:

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

Ответ 2

Принятый ответ - одно замечательное решение, но если вы хотите изменить порядок полей в результатах (что-то, что я должен был сделать недавно), это может не сработать. Вот альтернатива:

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 ;

При группировке по определенным полям выбор будет иметь уникальные значения для группы в каждом кортеже.

Ответ 3

Для вашего указанного ввода/вывода выполняется следующее. Вы можете обновить тестовые векторы, чтобы уточнить, что вам нужно, что отличается от этого.

A_unique = DISTINCT A;

Ответ 4

Вот два возможных решения, есть ли другие хорошие подходы?

Решение 1 (с использованием 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);
};

Решение 2 (с использованием 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);
};

Ответ 5

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