SQL实战:04之SQL中的分组问题求解

文章目录

概述

最近刷题时遇到一些比较有意思的题目,乍一遇上时还不知道怎么求解,在灵光一闪时找到了问题的求解答案,感觉还比较有意思。题目虽然不是很难,但是要解答出来还是需要有一点思维的转弯,为了加深记忆,就选取了一道记录下来。

题目:分组问题求解

如下为电商公司用户访问时间数据,某个用户连续的访问记录如果时间间隔小于 60 秒,则分为同一个组.

表logs

字段名 数据类型
id bigint
ts bigint

输入数据如下:

id ts(秒)
1001 17523641234
1001 17523641256
1002 17523641278
1001 17523641334
1002 17523641434
1001 17523641534
1001 17523641544
1002 17523641634
1001 17523641638
1001 17523641654

参考结果:

id ts(秒) group
1001 17523641234 1
1001 17523641256 1
1001 17523641334 2
1001 17523641534 3
1001 17523641544 3
1001 17523641638 4
1001 17523641654 4
1002 17523641278 1
1002 17523641434 2
1002 17523641634 3

题解

第一步:求解差值

因为需要按照id分组,求解每个用户连续访问时间间隔小于60秒,则放在同一组,所以需要使用窗口函数,将上一行的ts移动到下一行,进行差值运算。

需要用到的知识点:

  • PARTITION BY
  • LAG():下移值
SQL 复制代码
WITH temp_001 AS (
    SELECT id
        ,ts
        ,ts - LAG(ts,1,ts) OVER (PARTITION BY id ORDER BY ts ASC) AS ts_diff
    FROM logs
)

输出如下:

id ts ts_diff
1001 17523641234 17523641234
1001 17523641256 22
1001 17523641334 78
1001 17523641534 200
1001 17523641544 10
1001 17523641638 94
1001 17523641654 16
1002 17523641278 17523641278
1002 17523641434 156
1002 17523641634 200

步骤二:窗口分组累加

由上面的中间结果我们已经得出了一个ts的差值ts_diff,按照滑动 窗口顺序遍历窗口中的每一行数据,如果ts_diff的值大于指定的值60,则加1,否则加0。

第一行ts_diff的值大于60,则加1结果是1,然后第二行值为22加0,值还是为1

第二行和第一行的分组id就都是1了,分在了同一组达到了我们想要的效果。

第三行ts_diff的值是78大于60,加1结果为2,组的ID变成了2。

其他的依次如上。

SQL实现:

sql 复制代码
SELECT id
    ,ts
    ,SUM(IF(ts_diff>60,1,0)) OVER(PARTITION BY id  ORDER BY ts ASC) AS group
FROM temp_001

输出结果:

id ts(秒) group
1001 17523641234 1
1001 17523641256 1
1001 17523641334 2
1001 17523641534 3
1001 17523641544 3
1001 17523641638 4
1001 17523641654 4
1002 17523641278 1
1002 17523641434 2
1002 17523641634 3

完整SQL

SQL 复制代码
WITH temp_001 AS (
    SELECT id
        ,ts
        ,ts - LAG(ts,1,ts) OVER (PARTITION BY id ORDER BY ts ASC) AS ts_diff
    FROM logs
)
SELECT id
    ,ts
    ,SUM(IF(ts_diff>60,1,0)) OVER(PARTITION BY id  ORDER BY ts ASC) AS group
FROM temp_001;

总结

这道题考察的知识点就是对窗口的理解和运用,第一步下移并做差值运算一般都可以快速想到,第二步就需要一点点思维的闪光。利用IF做归一话处理并使用滑动窗口求和得到分组的组号。

相关推荐
Dovis(誓平步青云)11 分钟前
现场问题先关闭还是先验收,建筑任务怎样处理依赖
前端·javascript·数据库·mysql·音视频
dishugj16 分钟前
HANA监控、巡检与切换演练
数据库·oracle
a努力。39 分钟前
四维解析Agent记忆架构:从零实战LangGraph长期记忆
java·开发语言·数据库
ss2731 小时前
PG实战笔记 | 04 PostgreSQL市场地位与实际案例
数据库·postgresql
众链网络1 小时前
Agent 重试的工程解法:幂等、断点续跑与熔断怎么落地
java·前端·数据库·人工智能
oradh1 小时前
Oracle 索引维护操作总结
数据库·oracle
for_ever_love__1 小时前
MySQL Online DDL 完全指南:INSTANT/INPLACE/COPY 三种算法、MDL 锁事故与 gh-ost 实战
数据库·mysql·ddl·online·gh-ost·锁表·加字段
for_ever_love__2 小时前
MySQL 子查询、派生表与 CTE 优化:半连接、物化和递归实战
数据库·mysql·优化·as·子查询·with·cte
DBA_G2 小时前
GBase 8c分布式数据库客户端工具 gsql
数据库·分布式
用户5611610232732 小时前
量化笔记程序代码分析,逐笔数据、五档快照和分钟行情代码分析
数据库