使用 Apache Spark SQL 对结果进行子分组

Riy*_*yaz 0 sql window-functions gaps-and-islands apache-spark apache-spark-sql

我有以下事件表,我想将它们分组为较小的时间段,如下所示。

该表必须分为较小的集合,其中集合的起始行和结束行由 geohash 确定,如果 geohash 相同,则集合保留包含行,直到发现下一个 geohash 不同。

key time_stamp  geohash
k1  1           abcdfg
k1  5           abcdfg
k1  7           abcdf1
k1  9           abcdfg
k1  10          abcdf2
k1  12          abcdf2
k1  21          abcdf2
Run Code Online (Sandbox Code Playgroud)

如何使用 Apache Spark SQL 语法生成以下输出

key geohash first_time  last_time   duration    num_events
k1  abcdfg  1           5           4           2
k1  abcdf1  7           7           0           1
k1  abcdfg  9           9           0           1
k1  abcdf2  10          21          11          3
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我实现这一目标吗?

GMB*_*GMB 5

这是一种缺口与岛屿问题。row_number()这是使用聚合来解决该问题的一种方法:

select
    key, 
    geohash, 
    min(timestamp) first_time,
    max(timestamp) last_time,
    max(timestamp) - min(timestamp) duration,
    count(*) num_events
from (
    select
        t.*,
        row_number() over(partition by key order by timestamp) rn1,
        row_number() over(partition by key, geohash order by timestamp) rn2
    from mytable t
) t
group by 
    key,
    geohash,
    rn1 - rn2
Run Code Online (Sandbox Code Playgroud)

而且,只是为了好玩:您也可以使用条件窗口总和来做到这一点:

select
    key, 
    geohash, 
    min(timestamp) first_time,
    max(timestamp) last_time,
    max(timestamp) - min(timestamp) duration,
    count(*) num_events
from (
    select
        t.*,
        sum(case when lag_geohash = geohash then 0 else 1 end) 
            over(partition by key order by timestamp) grp
    from (
        select
            t.*,
            lag(geohash) over(partition by key order by timestamp) lag_geohash
        from mytable t
    ) t 
) t
group by 
    key,
    geohash,
    grp
Run Code Online (Sandbox Code Playgroud)