如何在列的子集上执行Pig Latin中的DISTINCT?

时间:2013-09-25 22:39:05

标签: apache-pig

我想对列的子集执行DISTINCT操作。 documentation表示使用嵌套的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)

6 个答案:

答案 0 :(得分:19)

在所有其他列上进行分组,将感兴趣的列投影到一个包中,然后使用FLATTEN将它们再次展开:

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

答案 1 :(得分: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 ;

当您对某些字段进行分组时,选择将在每个元组中具有该组的唯一值。

答案 2 :(得分:1)

对于您指定的输入/输出,以下工作。您可以更新您的测试向量,以阐明您需要的与此不同的内容。

A_unique = DISTINCT A;

答案 3 :(得分:0)

以下是两种可能的解决方案,还有其他好方法吗?

解决方案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);
};

答案 4 :(得分:0)

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

答案 5 :(得分:0)

我一直想做同样的事情:“我想对列的子集执行DISTINCT操作”。我这样做的方式是:

A = LOAD 'data' AS(a1,a2,a3,a4);
interested_fields = FOREACH A GENERATE a1,a2,a3;
distinct_fields= DISTINCT interested_fields;
final_answer = FOREACH distinct_fields GENERATE FLATTEN($0);

我知道这不是文档中建议的如何执行嵌套的foreach的示例;但这是对字段子集进行区分的一种方法。希望它对像我一样来到这里的人有所帮助。