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做归一话处理并使用滑动窗口求和得到分组的组号。

相关推荐
“αβ”3 小时前
MySQL表的操作
linux·网络·数据库·c++·网络协议·mysql·https
p***s913 小时前
Spring数据库原理 之 DataSource
java·数据库·spring
虹科网络安全3 小时前
艾体宝干货 | Redis Java 开发系列#1 从零开始的环境搭建与实践指南
java·数据库·redis
火山引擎开发者社区3 小时前
火山引擎向量数据库 Milvus 版正式商业化:AI 时代的向量检索新标杆
数据库·milvus·火山引擎
神秘的土鸡4 小时前
openEuler 25.09 企业级 MySQL主从复制部署与性能优化实战提升50%
linux·数据库·mysql·性能优化·openeuler
韩立学长4 小时前
基于Springboot课堂教学辅助系统08922bq1(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
goxingman5 小时前
Oracle视图基础
数据库·oracle
黎相思5 小时前
MySQL索引特性
数据库·mysql
rit84324996 小时前
压缩感知信号恢复算法:OMP与CoSaMP对比分析
数据库·人工智能·算法