pig-如何只从列表中选择一些值(而不仅仅是简单的distinct)?

pvabu6sv  于 2021-06-03  发布在  Hadoop
关注(0)|答案(2)|浏览(372)

假设我有intput\u file.txt(用户id、事件代码、事件日期):

1,a,1
1,b,2
2,a,3
2,b,4
2,b,5
2,b,6
2,c,7
2,b,8

如您所见,user\u id=2有如下事件: abbbcb 我想得到这样的结果:

1,{(a,1),(b,2)}
2,{(a,2),(b,6),(c,7),(b,8)}

所以当我们有几个事件时,使用相同的代码,我只想取最后一个。
你能分享一些提示吗?
向帕维尔问好

fjnneemd

fjnneemd1#

似乎可以使用apachedatafu的distinctby udf来实现这一点。给定一个包,这个udf返回为给定字段找到的第一个示例。在您的例子中,您关心的字段是事件代码。但我们必须颠倒顺序,因为你实际上想要最后一个示例。
不过有一点需要澄清。如果我错了,请纠正我,但我认为预期的输出是:

1,{(a,1),(b,2)}
2,{(a,3),(b,6),(c,7),(b,8)}

也就是说,成员2发生(a,3)事件。成员1发生(a,2)事件。
你可以这样做:

-- pass in 1 because we want distinct by event code (position 1)
define DistinctBy datafu.pig.bags.DistinctBy('1');

FOREACH (GROUP A BY user_id) {
  -- reverse so we can take the last event code occurrence
  A_reversed = ORDER A BY event_date DESC;

  -- use DistinctBy to get the first tuple having an occurrence of a field value
  A_distinct_by_code = DistinctBy(A_reversed);

  -- put back in order again
  A_ordered = ORDER A_distinct_by_code BY event_date ASC;

  GENERATE group as user_id, A_ordered.(event_code,event_date);
}
xqnpmsa8

xqnpmsa82#

你描述的主要内容是什么 GROUP BY 做。
在这种情况下:

B = GROUP A BY user_id;

把你的记录整理好 user_id . 您的数据现在如下所示:

1,{(a,1),(b,2)}
2,{(a,2),(b,6),(c,7),(b,8)}

你说你只想要最后一个(我想你指的是最棒的那个) event_date ). 为此,可以执行嵌套 FOREACH 带着一个 ORDER BY 按日期排序,然后用 LIMIT . 请注意,当存在关系时,这具有任意行为。

C = FOREACH B {                          
   DA = ORDER A BY event_date DESC;                
   DB = LIMIT DA 1;                         
   GENERATE FLATTEN(group), FLATTEN(DB.event_code), FLATTEN(DB.event_date);
}

您的数据现在应该如下所示:

1,b,2
2,b,8

另一种选择是使用自定义项在给定的组上编写一些自定义行为 GROUP BY :

B = GROUP A BY user_id;
C = FOREACH B GENERATE YourUDFThatYouBuilt(group, A);

在这个udf中,您可以编写任何您想要的自定义行为(在本例中,返回具有最大日期的元组)

相关问题