Hive SQL,在滑动10分钟窗口中查找最大计数

时间:2018-01-09 21:11:32

标签: hadoop hive hiveql

我有一张大致(超简化)的表格

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,因为ABC在彼此的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的窗口

2 个答案:

答案 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 (..)