当列在 Clickhouse 中随时间变化时分组和聚合
Posted
技术标签:
【中文标题】当列在 Clickhouse 中随时间变化时分组和聚合【英文标题】:Group by and aggregate when colums change over time in Clickhouse 【发布时间】:2021-08-09 05:36:51 【问题描述】:假设我在 Clickhouse 中有下表:
f_datetime, f_user, f_tile
2021-07-08 07:00:00, x, a
2021-07-08 08:30:00, x, a
2021-07-08 08:45:00, x, a
2021-07-08 09:00:00, x, b
2021-07-08 11:00:00, x, b
2021-07-08 12:00:00, x, a
2021-07-08 15:00:00, x, a
2021-07-08 16:00:00, x, b
2021-07-08 20:00:00, x, b
我想要一个聚合查询来获得以下结果:
f_user, f_tile, f_duration
x, a, 105
x, b, 120
x, a, 180
x, b, 240
我想在 f_datetime 之前对 f_tile、f_user 进行分组并计算持续时间。
有什么解决办法吗?
【问题讨论】:
***.com/questions/61163259/… 【参考方案1】:这是一个间隙和孤岛问题的示例。对于这个版本,最简单的解决方案可能是行号的不同:
select f_user, t_tile,
min(f_datetime), max(f_datetime),
date_diff('minute', min(f_datetime), max(f_datetime)) as f_duration
from (select t.*,
row_number() over (partition by f_user order by f_datetime) as seqnum,
row_number() over (partition by f_user, f_tile order by f_datetime) as seqnum_2
from t
) t
group by f_user, f_tile, (seqnum - seqnum_2)
【讨论】:
【参考方案2】:表中的下一个日期时间值是该用户的最小值,>= 当前行的日期时间。
SELECT t.f_user, t.f_title,
(SELECT MIN(t1.f_datetime)
FROM Yourtable t1
WHERE t1.f_datetime >= t.f_datetime AND t1.f_user = t.f_user AND t1.f_tile = t.f_tile) - t.f_datetime
FROM Yourtable t
您可以应用 DIFF 函数,而不是减去这些值。
【讨论】:
【参考方案3】:由于您希望对每个连续的 f_tile
段进行计算(我猜是 f_user
),这里有一种方法,使用窗口函数:
f_tile
的边缘,每个 f_user
运行
cte3:为每次运行计算一个组 (grp
) 指标以进行聚合
cte4:计算每次f_tile
运行的持续时间
WITH cte2 AS ( -- Find edges of each f_tile run for each f_user by datetime
SELECT t.*
, CASE WHEN LAG(f_tile) OVER (PARTITION BY f_user ORDER BY f_datetime) = f_tile THEN 0 ELSE 1 END AS edge
FROM data AS t
)
, cte3 AS ( -- Assign a group (grp) indicator for each run for aggregation
SELECT t.*, SUM(edge) OVER (PARTITION BY f_user ORDER BY f_datetime) AS grp
FROM cte2 AS t
)
, cte4 AS (
SELECT f_user, f_tile, grp
, MIN(f_datetime) AS start
, DATE_DIFF('minute', MAX(f_datetime), MIN(f_datetime)) AS duration
FROM cte3 AS t
GROUP BY f_user, f_tile, grp
)
SELECT f_user, f_tile, duration
FROM cte4
ORDER BY start
;
结果:
+--------+--------+----------+
| f_user | f_tile | duration |
+--------+--------+----------+
| x | a | 105 |
| x | b | 120 |
| x | a | 180 |
| x | b | 240 |
+--------+--------+----------+
注意:我没有要测试的 clickhouse 实例。根据需要进行调整。我已经用另一个引擎测试了等效项。
【讨论】:
以上是关于当列在 Clickhouse 中随时间变化时分组和聚合的主要内容,如果未能解决你的问题,请参考以下文章
当列数不相等而不将每个列定义为 NuLL 时,有没有办法在 Impala SQL 中合并两个表