【发布时间】:2011-09-29 16:56:12
【问题描述】:
我在 Hive 中有两个表,t1 和 t2
>describe t1;
>date_id string
>describe t2;
>messageid string,
createddate string,
userid int
> select * from t1 limit 3;
> 2011-01-01 00:00:00
2011-01-02 00:00:00
2011-01-03 00:00:00
> select * from t2 limit 3;
87211389 2011-01-03 23:57:01 13864753
87211656 2011-01-03 23:57:59 13864769
87211746 2011-01-03 23:58:25 13864785
我想要的是计算给定日期前三天的不同用户 ID。
例如,对于日期2011-01-03,我想计算从2011-01-01 到2011-01-03 的不同用户ID。
对于日期2011-01-04,我想计算从2011-01-02 到2011-01-04 的不同用户ID
我写了以下查询。但它不会返回三天的结果。而是每天返回不同的用户 ID。
SELECT to_date(t1.date_id), count(distinct t2.userid) FROM t1 JOIN t2
ON (to_date(t2.createddate) = to_date(t1.date_id))
WHERE date_sub(to_date(t2.createddate),0) > date_sub(to_date(t1.date_id), 3)
AND to_date(t2.createddate) <= to_date(t1.date_id)
GROUP by to_date(t1.date_id);
`to_date()` and `date_sub()` are date function in Hive.
也就是说,下面的部分不生效。
WHERE date_sub(to_date(t2.createddate),0) > date_sub(to_date(t1.date_id), 3)
AND to_date(t2.createddate) <= to_date(t1.date_id)
编辑:一种解决方案可以是(但速度非常慢):
SELECT to_date(t3.date_id), count(distinct t3.userid) FROM
(
SELECT * FROM t1 LEFT OUTER JOIN t2
WHERE
(date_sub(to_date(t2.createddate),0) > date_sub(to_date(t1.date_id), 3)
AND to_date(t2.createddate) <= to_date(t1.date_id)
)
) t3
GROUP by to_date(t3.date_id);
更新:感谢所有答案。他们很好。
但是 Hive 与 SQL 有点不同。不幸的是,它们不能在 HIVE 中使用。
我目前的解决方案是使用UNION ALL。
SELECT * FROM t1 JOIN t2 ON (to_date(t1.date_id) = to_date(t2.createddate))
UNION ALL
SELECT * FROM t1 JOIN t2 ON (to_date(t1.date_id) = date_add(to_date(t2.createddate), 1)
UNION ALL
SELECT * FROM t1 JOIN t2 ON (to_date(t1.date_id) = date_add(to_date(t2.createddate), 2)
然后,我做group by 和count。这样,我就能得到我想要的。
虽然不优雅,但比cross join效率高很多。
【问题讨论】: