我有一大堆事件。每个用户我想在最早的B类事件之前计算A类事件的发生。
我正在寻找一个优雅的查询。使用Hive所以我不能做子查询
Timestamp Type User
... A X
... A X
... B X
... A X
... A X
... A Y
... A Y
... A Y
... B Y
... A Y
通缉结果:
User Count_Type_A
X 2
Y 3
我无法通过以下方式获得“截止”时间戳:
Select User, min(Timestamp)
Where Type=B
Group BY User;
但是,我如何在下一个查询中使用该信息,我想做的事情如下:
SELECT User, count(Timestamp)
WHERE Type=A AND Timestamp<min(User.Timestamp_Type_B)
GROUP BY User;
到目前为止,我唯一的想法是首先确定截止时间戳,然后对所有类型A事件进行连接,然后从结果表中选择,但这感觉不对,看起来很难看。
我也在考虑这是Hive问题/分析的错误类型的可能性,我应该考虑手写的map-reduce或pig。
请指出正确的方向帮助我。
答案 0 :(得分:1)
第一次更新:
针对Cilvic对此答案的第一次评论,我根据https://issues.apache.org/jira/browse/HIVE-556上的评论中建议的解决方法将我的查询调整为以下内容:
SELECT [User], COUNT([Timestamp]) AS [Before_First_B_Count]
FROM [Dataset] main
CROSS JOIN (SELECT [User], min([Timestamp]) [First_B_TS] FROM [Dataset]
WHERE [Type] = 'B'
GROUP BY [User]) sub
WHERE main.[Type] = 'A'
AND (sub.[User] = main.[User])
AND (main.[Timestamp] < sub.[First_B_TS])
GROUP BY main.[User]
<强>原始强>
试一试:
SELECT [User], COUNT([Timestamp]) AS [Before_First_B_Count]
FROM [Dataset] main
JOIN (SELECT [User], min([Timestamp]) [First_B_TS] FROM [Dataset]
WHERE [Type] = 'B'
GROUP BY [User]) sub
ON (sub.[User] = main.[User]) AND (main.[Timestamp] < sub.[First_B_TS])
WHERE main.[Type] = 'A'
GROUP BY main.[User]
我尽力遵循hive语法。如果您有任何疑问,请告诉我。我想知道为什么你希望/需要避免子查询。
答案 1 :(得分:1)
一般来说,我是+1 coge.soft的解决方案。这里再次供您参考:
SELECT [User], COUNT([Timestamp]) AS [Before_First_B_Count]
FROM [Dataset] main
JOIN (SELECT [User], min([Timestamp]) [First_B_TS] FROM [Dataset]
WHERE [Type] = 'B'
GROUP BY [User]) sub
ON (sub.[User] = main.[User]) AND (main.[Timestamp] < sub.[First_B_TS])
WHERE main.[Type] = 'A'
GROUP BY main.[User]
然而,有几点需要注意:
没有B事件时会发生什么?假设您希望在这种情况下计算每个用户的所有A事件,则解决方案中指定的内部联接将不起作用,因为子表中没有该用户的条目。您需要更改为左外连接。
该解决方案还对数据进行了2次传递 - 一次填充子表,另一次用于将子表与主表连接。根据您的性能和效率概念,您可以通过单次传递数据来实现此目的。您可以使用Hive的distribute by功能按用户分发数据,并编写一个自定义缩减器,使用Hive's transform functionality以您喜欢的语言进行计数计算。