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存储引擎与索引
数据库·sql·mysql
lzhdim5 小时前
SQL 入门 15:SQL 事务:从 ACID 到四种常见的并发问题
数据库·sql
瀚高PG实验室5 小时前
瀚高企业版V9.1.1在pg_restore还原备份文件时提示extract函数语法问题
数据库·瀚高数据库
TDengine (老段)5 小时前
TDengine Tag 设计哲学与 Schema 变更机制
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
YOU OU6 小时前
Spring IoC&DI
java·数据库·spring
Muscleheng7 小时前
Navicat连接postgresql时出现‘datlastsysoid does not exist‘报错
数据库·postgresql
罗超驿8 小时前
18.事务的隔离性和隔离级别:MySQL面试高频考点全解析
数据库·mysql·面试
jran-8 小时前
Redis 命令
数据库·redis·缓存
小江的记录本9 小时前
【Java基础】Java 8-21新特性:JDK21 LTS:虚拟线程、模式匹配switch、结构化并发、序列集合(附《思维导图》+《面试高频考点清单》)
java·数据库·python·mysql·spring·面试·maven
June`9 小时前
多线程redis下如何解决aof重写和rdb持久化的数据一致性问题
数据库·redis·缓存