我有一张大致(超简化)的表格
ts | session | other_stuff
------------------------------
100 | A | ...
101 | B | ...
101 | A | ...
102 | C | ...
103 | A | ...
104 | C | ...
104 | A | ...
9999 | D | ...
20000 | D | ...
ts
是存储为double的时间戳。我想在任何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的窗口
答案 0 :(得分:0)
非常有趣的问题。这就是我接触它的方式
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
与前一行ts
的{{1}}或后一行(lag)
之间的差异。 (lead)
方便,它提供前一行的lag(ts,1,0)
。但是有一个问题,如果当前行是第一行会发生什么?没问题,使用ts
lag(ts,1,0)
这里是没有前一行时返回的默认值。
现在我们需要做的是从当前行的0
中减去lag
返回的值并应用条件(您的时间窗口)。也就是说,检查当前ts
是否在600之内。
如果上一行的ts - lag_ts
比当前行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 |
+--------+------+------+-------+--+
答案 1 :(得分:0)
如果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存储在另一个存储桶中,依此类推。
根据您使用的hive版本 distinct 部分可能/可能不适用于count(distinct session) over (..)