Hive QL - 根据条件选择,分组在一行

时间:2015-08-27 01:34:37

标签: hive hiveql

我有一个日期分区的Hive表,每个用户都有一行。它有一个activity_log列,其值为1或0,具体取决于用户是否在该日期执行了该活动。

我也有一个UDF,就像dayOfWeek(),它给了我一周中某一天的日期。

我正在尝试创建一个包含过去一周用户活动的表。因此,列将是:

user, activity_log_mon, activity_log_tue, activity_log_wed, ...activity_log_sun

每个activity_log列的值应为1或0,表示用户是否在过去一周的那一天执行了该活动。

这是一个给我几乎所需的查询:

SELECT user,
IF(dayOfWeek(date)='sun', activity_log , NULL) as activity_log_sun,
IF(dayOfWeek(date)='mon', activity_log , NULL) as activity_log_mon,
IF(dayOfWeek(date)='tue', activity_log , NULL) as activity_log_tue,
IF(dayOfWeek(date)='wed', activity_log , NULL) as activity_log_wed,
IF(dayOfWeek(date)='thu', activity_log , NULL) as activity_log_thu,
IF(dayOfWeek(date)='fri', activity_log , NULL) as activity_log_fri,
IF(dayOfWeek(date)='sat', activity_log , NULL) as activity_log_sat
FROM user_activity_table
WHERE date >= '2015-08-18' AND date <= '2015-08-24'

但这会为每个用户提供7行,如下所示:

user    activity_log_sun    activity_log_mon   ....   activity_log_sat

abcd          1                  NULL                      NULL 
abcd         NULL                 0                        NULL
... 
abcd         NULL                NULL                       1

我真正想要的是一个每个用户只有一行的表,如下所示:

user    activity_log_sun    activity_log_mon   ....   activity_log_sat

abcd          1                   0                         1

如何重新组合这样的行?或者,首先获得这样的行的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

这是我最终做的事情:

SELECT user, 
       SUM(activity_log_sun),
       SUM(activity_log_mon),
       SUM(activity_log_tue),
       SUM(activity_log_wed),
       SUM(activity_log_thu),
       SUM(activity_log_fri),
       SUM(activity_log_sat)
FROM ( 
SELECT user,
IF(dayOfWeek(date)='sun', activity_log , NULL) as activity_log_sun,
IF(dayOfWeek(date)='mon', activity_log , NULL) as activity_log_mon,
IF(dayOfWeek(date)='tue', activity_log , NULL) as activity_log_tue,
IF(dayOfWeek(date)='wed', activity_log , NULL) as activity_log_wed,
IF(dayOfWeek(date)='thu', activity_log , NULL) as activity_log_thu,
IF(dayOfWeek(date)='fri', activity_log , NULL) as activity_log_fri,
IF(dayOfWeek(date)='sat', activity_log , NULL) as activity_log_sat
FROM user_activity_table
WHERE date >= '2015-08-18' AND date <= '2015-08-24'
) t
GROUP BY user

答案 1 :(得分:0)

观察以下HiveQL的行为:

SELECT COALESCE(collected[0], collected[1], collected[2], collected[3]) 
FROM(Select Array(NULL, 1, NULL, NULL) as collected) a;

这将1作为COALESCE函数的第一个非空值返回。然后看到有一个分组函数collect_list(col)

因此,如果我们将每个用户7行的输出称为activity_uncollected,那么您的最终转换将是:

SELECT user_id,
  COALESCE(collected_mon[0], collected_mon[1], ..., collected_mon[6]),
  ...
  COALESCE(collected_sun[0], collected_sun[1], ..., collected_sun[6])
FROM
  (SELECT user_id, 
     collect_list(activity_log_mon), 
     ..., 
     collect_list(activity_log_sun)
   FROM activity_uncollected 
   GROUP BY user_id) a;

将每个用户每天的所有值分组,然后从每个数组中选择非空值。

相关问题