Hive SQL,在滑动 10 分钟窗口中找到最大计数
Posted
技术标签:
【中文标题】Hive SQL,在滑动 10 分钟窗口中找到最大计数【英文标题】:Hive SQL, find max count in sliding 10 minute window 【发布时间】:2018-01-09 21:11:31 【问题描述】:我有一个大致(超级简化)的表格
ts | session | other_stuff
------------------------------
100 | A | ...
101 | B | ...
101 | A | ...
102 | C | ...
103 | A | ...
104 | C | ...
104 | A | ...
9999 | D | ...
20000 | D | ...
ts
是存储为双精度的时间戳。我想在任何 10 分钟窗口中找到最大活动会话数。因此,在上面的示例中,答案将是 3
,因为 A
、B
和 C
在 10 分钟内都处于活动状态。什么是正确的查询,我已经尝试了几件事,但遇到了错误,所以我肯定没有以正确的方式思考这个问题。
我尝试过
SELECT *,
(
SELECT COUNT(DISTINCT session)
FROM mytable mi
WHERE mi.ts BETWEEN m.ts - 300 AND m.ts + 300
) AS maxconcurrent
FROM mytable m
ORDER BY
maxconcurrent DESC
但收到错误
Presto query has failed. Unexpected node: com.facebook.presto.sql.planner.plan.LateralJoinNode
编辑:这是一个表格,其中窗口的滑动特性很重要
ts | session | other_stuff
------------------------------
100 | A | ...
201 | B | ...
301 | A | ...
702 | C | ...
1503 | A | ...
2504 | C | ...
3696 | A | ...
9999 | D | ...
20000 | D | ...
最大值仍然是 3,但现在它来自覆盖 201 到 801 的窗口
【问题讨论】:
如果您尝试过..请包括您的尝试。 在 ts 列中,什么是 10 分钟窗口? @VK_217 它的时间戳以秒为单位,因此正负 300 秒是一个 600 秒(10 分钟)的窗口 在您的第二组数据示例中,计数不能为 3。它是 2。只有 A 和 B @BalaB @ 201
+ A @ 301
+ C @ 702
= 3 在 600 秒内。
【参考方案1】:
非常有趣的问题。这是我的处理方法
select * from sliding
+-------------+----------------+--+
| sliding.ts | sliding.users |
+-------------+----------------+--+
| 100 | A |
| 101 | B |
| 101 | A |
| 102 | C |
| 103 | A |
| 104 | C |
| 104 | A |
| 9999 | D |
| 20000 | D |
+-------------+----------------+--+
我们现在需要计算当前行的ts
与前一行(lag)
或下一行(lead)
的ts
之间的差异。 lag(ts,1,0)
很方便,它提供了前一行的ts
。但是有一个问题,如果当前行是第一行会发生什么?没问题,使用lag(ts,1,0)
0
这里是没有前行时返回的默认值。
现在我们需要做的就是从当前行的ts
中减去lag
返回的值并应用条件(您的时间窗口)。即检查当前ts - lag_ts
是否在600以内。
如果前一行的ts
比当前行的ts
高得多,有人可能会认为这会失败?但它不会,因为over
子句有order by ts
。
select users, ts, lag, lead from (
select users, ts,
lag(ts,1,0) over (order by ts) as lag,
lead(ts,1) over( order by ts) as lead
from sliding ) tbl
where (ts - lag) <= 600
+--------+------+------+-------+--+
| users | ts | lag | lead |
+--------+------+------+-------+--+
| A | 100 | 0 | 101 |
| A | 101 | 100 | 101 |
| B | 101 | 101 | 102 |
| C | 102 | 101 | 103 |
| A | 103 | 102 | 104 |
| A | 104 | 103 | 104 |
| C | 104 | 104 | 9999 |
+--------+------+------+-------+--+
应用不同的计数得到
select count(distinct users) from (
select users, ts,
lag(ts,1,0) over (order by ts) as lag,
lead(ts,1) over( order by ts) as lead
from sliding ) tbl
where (ts - lag) <= 600
+------+--+
| _c0 |
+------+--+
| 3 |
+------+--+
【讨论】:
这当然更接近答案,但我相信这意味着窗口是固定的 3 行宽对吧? 我不确定我是否理解了您的问题。请您详细说明一下? 如果我猜到了,您想知道窗口是否是固定编号。 3 行。答案是否定的。这取决于time
窗口和满足窗口条件的行数(就像正常的 where 子句一样)。尝试增加/减少300
,添加更多具有不同ts
的行。
您可能知道,如果需要,它可以限制为 3 行。
可能我看不懂lag
和lead
(很有可能)让我试一试。【参考方案2】:
如果 hive 允许窗口具有动态边界宽度,我不是用户,据我所知,它只支持固定窗口宽度
但是看看这是否适合你。使用floor
舍入最接近的第 10 分钟时间戳并进行分析。
select ts, session , count(distinct session) over (partition by floor((ts+599)/600) * 600) from your_table;
您的结果将如下所示:
ts | session | cnt
------------------------------
100 | A | 2
201 | B | 2
301 | A | 2
702 | C | 1
floor((ts+599)/600) * 600)
- 这使得时间戳为 0 - 600 的会话将落入一个存储桶,601-1200 进入另一个存储桶,依此类推。
根据您使用的配置单元版本不同部分可能/可能不适用于count(distinct session) over (..)
【讨论】:
以上是关于Hive SQL,在滑动 10 分钟窗口中找到最大计数的主要内容,如果未能解决你的问题,请参考以下文章