HIVE使用列作为索引并使用聚合作为值来构造ARRAY

时间:2015-09-23 06:53:07

标签: hive hiveql

我有一张表,其中包含ip,session_id,小时。 我希望聚合这些数据并最终得到一个新表,该表具有每个ip的记录,其中包含每小时聚合会话数的数组。

为此,我开始使用子查询

SELECT ip, count(session_id) as sessions, hour
FROM current_table
GROUP BY ip,hour;

这将为每个IP提供(最多)24条记录,并在相应记录中显示特定小时的会话数。使用这个子查询我想要填充一个数组(比如说hourly_sessions是我正在使用的数组),比如,

hourly_sessions[hour] = sessions

所以我最终得到一个与每个ip和数组索引关联的数组代表我想要检查会话聚合的小时。如果特定小时内没有会话,我希望它显示0。

如何在HIVE中使用/不使用UDF来实现此目的? 我当前(hacky和不完整)的方法是使用类似的东西:

collect_set(concat_ws(",",hour,cast(sessions) as STRING)) 

但这需要在每次需要特定的每小时聚合时解析整个数组。

1 个答案:

答案 0 :(得分:0)

首先,我认为您需要了解如何填补数据中的任何空白。就(ip,hour)对而言。一种方法是创建一个小时表:

CREATE TABLE HOURS AS Select explode(Array(0,1,2...,23)) as hour;

然后是一张不同的IPS表:

CREATE TABLE IPS AS SELECT distinct ip from current_table;

然后加入他们:

CREATE TABLE IP_HOURS AS SELECT IPS join HOURS;

这为每个IP提供了23个条目。加上你的实际数量:

CREATE TABLE ACTUAL_COUNTS AS 
  SELECT ip, count(session_id) as sessions, hour
  FROM current_table
  GROUP BY ip,hour;

CREATE TABLE NO_GAP_COUNTS AS
    SELECT a.ip as ip, a.hour as hour, COALESCE(b.sessions, 0) as sessions
    FROM IP_HOURS a LEFT JOIN ACTUAL_COUNTS b ON (a.ip = b.ip AND a.hour = b.hour)

您可以按原样使用此表,但如果您确实要将每小时的计数压缩到一个数组中,这样每个ID就有一行,那么您可以使用Brickhouse“收集”UDF,因为它将维持会话计数,如果您通过ip,小时首先订购数据。内置的Hive collect_set不保证保留顺序。

Is Hive's collect_list ordered?