SQL中countinues状态的聚合

Posted

技术标签:

【中文标题】SQL中countinues状态的聚合【英文标题】:Aggregation on countinues status in SQL 【发布时间】:2020-05-08 09:43:16 【问题描述】:

我正在处理一些包含playend 的播放状态日志数据。在游戏过程中,客户端会多次报告play,但当出现end时,表示游戏结束,比如

user_id  status  timestamp
   a      play    xxx
   a      play    xxx
   a      play    xxx
   a      end     xxx
   b      play    xxx
   b      end     xxx
   c      play    xxx
   c      play    xxx
   c      end     xxx
   a      play    xxx
   a      play    xxx
   a      end     xxx
   a      play    xxx
   a      end     xxx

现在,我可以使用row_number() 来计算user_id 的数量与超过2 个play 状态的游戏类似:

# I realize this is a wrong query...

select count(distinct user_id) as cnt_uid
    (select  
        user_id,status,timestamp, 
        row_number() over (partition by user_id, status, order by timestamp) as rn
    from tableA) a
    where rn>=2 

但是如果我需要计算超过 2 个play 状态的游戏数量(例如:user A 有 2 个游戏超过 2 个play 状态,user C 有 1 个),该怎么做?任何帮助表示赞赏。

*PS:预期结果只是一些游戏的状态超过 2 个play,对于上面给出的数据,结果是3

【问题讨论】:

如果在 hive 中可用,您可以使用 DENSE_RANK() @DigvijayS 感谢您的回复。我在Hive 中尝试了dense_rank() over (order by status),我认为结果等同于user_id...如果我没有以正确的方式使用它,请随时告诉我.... 您能否通过编辑您的帖子添加预期输出。 嗨@DigvijayS 我刚刚修改了帖子,实际上,这种情况下的预期输出只是一个数字:3 【参考方案1】:

您可以使用status = 'end' 的累积总和来定义“游戏”。然后再聚合再聚合:

select user_id, count(*) as games_with_2+_plays
from (select user_id, grp, count(*) as num_plays
      from (select t.*,
                   sum(case when status = 'end' then 1 else 0 end) over (partition by user_id order by timestamp) as grp
            from t
           ) t
      where status = 'play'
      group by user_id, grp
     )
where num_plays >= 2
group by user_id;

【讨论】:

感谢您的精彩回答!!!在您的查询中,status = 'end' 被删除,这是可行的。如果我需要每场比赛的时间间隔(时间间隔=end时间戳-每场比赛的第一个play的时间戳),如何计算? @user2894829 。 . .你会做类似min(timestamp)max(timestamp)之间的区别。

以上是关于SQL中countinues状态的聚合的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQL 对具有共同状态的连续项目进行分组(包括虚拟数据)

SQL 连接,使用 Pivot 聚合

跨多个表聚合 SQL 查询

SQL按照年月员工状态统计出勤情况

SQL按照年月员工状态统计出勤情况

SqlServer如何用Sql语句自定义聚合函数