SQL 知识点训练 12
知识点
- 分组统计
- 嵌套查询
- 窗口函数over的详细使用
- 求和函数 sum
创建表
DROP TABLE IF EXISTS tb_user_log;
CREATE TABLE tb_user_log (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid INT NOT NULL COMMENT '用户ID',
artical_id INT NOT NULL COMMENT '视频ID',
in_time datetime COMMENT '进入时间',
out_time datetime COMMENT '离开时间',
sign_in TINYINT DEFAULT 0 COMMENT '是否签到'
) CHARACTER SET utf8 COLLATE utf8_bin;
INSERT INTO tb_user_log(uid, artical_id, in_time, out_time, sign_in) VALUES
(101, 9001, '2021-11-01 10:00:00', '2021-11-01 10:00:11', 0),
(102, 9001, '2021-11-01 10:00:09', '2021-11-01 10:00:38', 0),
(103, 9001, '2021-11-01 10:00:28', '2021-11-01 10:00:58', 0),
(104, 9002, '2021-11-01 11:00:45', '2021-11-01 11:01:11', 0),
(105, 9001, '2021-11-01 10:00:51', '2021-11-01 10:00:59', 0),
(106, 9002, '2021-11-01 11:00:55', '2021-11-01 11:01:24', 0),
(107, 9001, '2021-11-01 10:00:01', '2021-11-01 10:01:50', 0);
实战练习
统计每篇文章同一时刻最大在看人数,如果同一时刻有进入也有离开时,先记录用户数增加再记录减少,结果按最大人数降序。
难度
思路一
思路:先算出每组artical_id的所有时刻的在看人数
,再用group by
语句找出每组artical_id
最大的在看人数。那么怎么求每个时刻的在看人数呢?
可以这么理解:in_time的时刻在看人数+1
,out_time时刻在看人数-1
,每一组artical_id内进行在看人数变化量按时间顺序的累加就可以算出每个时刻在看的人数,最后找出每组artical_id内最大的在看人数就是题目要求的同一时刻最大在看人数了。
理清思路后再来想SQL语句
:
第一个难点在于UNION ALL
的使用,这里是我没有想到的。in_time和out_time两种类别的人数变化可以直接用UNION ALL来处理。时刻dt有两种:in_time和out_time,人数变化量是diff有两种:+1和-1,union all连接后可以直接进行累加算出某时刻在看人数。
累积值的计算往往采用窗口函数,那么用sum(diff)over(partition by artical_id,order by dt),这里有个小细节,题目要求同一时刻先算增加的再算减少的,所以order by后还要加个diff desc字段
。
最后求最大值是按artical_id
分组
先进行思路拆分 :
先将退出 和 进入的数据合并起来
然后通过上面的分析 使用 artical_id 进行数据 Group by 然后通过 Max 进行最大值的查询
难点
主要是 over 的使用
思路二
首先是对计算某一时刻同时在线人数的思路
对进出状态进行1,-1编码,这样使用窗口函数按时间顺序汇总一下就可以求出每个时刻的在线人数。这是一个非常实用的一个思路👍👍👍
比较容易出现的思维误区
如果同一时刻有进入也有离开时,先记录用户数增加再记录减少
比如在某一秒钟有人进来也有人出去,那个此时的计算顺序应该是在进来时先加一,出去时再减一,如果没有特意这一点的话,那么进来跟出去两个时间的人数都应该是不加不减。
这就要求使用窗口函数时,不仅要按时间排序,还要按出入顺序进行排序
转载自:https://juejin.cn/post/7173228334040481828