表:Sessions
+---------------------+---------+
| Column Name | Type |
+---------------------+---------+
| session_id | int |
| duration | int |
+---------------------+---------+
session_id 是该表主键
duration 是用户访问应用的时间, 以秒为单位
你想知道用户在你的 app 上的访问时长情况。因此你决定统计访问时长区间分别为 "[0-5>","[5-10>","[10-15>" 和 "15 minutes or more" 的会话数量,并以此绘制柱状图。
写一个解决方案来报告 (bin, total) 。
返回结果 无顺序要求 。
结果格式如下所示。
示例 1:
输入:
Sessions 表:
+-------------+---------------+
| session_id | duration |
+-------------+---------------+
| 1 | 30 |
| 2 | 199 |
| 3 | 299 |
| 4 | 580 |
| 5 | 1000 |
+-------------+---------------+
输出:
+--------------+--------------+
| bin | total |
+--------------+--------------+
| [0-5> | 3 |
| [5-10> | 1 |
| [10-15> | 0 |
| 15 or more | 1 |
+--------------+--------------+
解释:
对于 session_id 1,2 和 3 ,它们的访问时间大于等于 0 分钟且小于 5 分钟。
对于 session_id 4,它的访问时间大于等于 5 分钟且小于 10 分钟。
没有会话的访问时间大于等于 10 分钟且小于 15 分钟。
对于 session_id 5, 它的访问时间大于等于 15 分钟。
解法思路:
1. 单位换算
首先,题目给出的 duration 是秒,但区间是分钟。为了计算方便且避免除法带来的精度问题,我们先把分钟换算成秒:
-
0-5 分钟:[0, 300) 秒
-
5-10 分钟:[300, 600) 秒
-
10-15 分钟:[600, 900) 秒
-
15 分钟以上:>= 900 秒
2. 核心难点:零值保留
题目的潜台词是:即使某个区间没有数据,也必须显示该区间,且数量为 0。
如果使用常规的 GROUP BY + CASE WHEN,一旦某个区间没数据,那个区间直接就不会出现在结果里(行丢失),导致答案错误。
3. 策略选择:分而治之 (Divide and Conquer)
既然只有 4 个固定的类别,我们可以把这个问题拆解成 4 个独立的小问题:
-
Q1: 统计 [0, 300) 的数量(如果没有就是 0)
-
Q2: 统计 [300, 600) 的数量
-
...
最后用胶水 (UNION ALL) 把它们粘在一起。
代码:
sql
SELECT '[0-5>' AS bin, COUNT(*) AS total sql
FROM Sessions
WHERE duration >= 0 AND duration < 300
UNION ALL
SELECT '[5-10>' AS bin, COUNT(*) AS total
FROM Sessions
WHERE duration >= 300 AND duration < 600
UNION ALL
SELECT '[10-15>' AS bin, COUNT(*) AS total
FROM Sessions
WHERE duration >= 600 AND duration < 900
UNION ALL
SELECT '15 or more' AS bin, COUNT(*) AS total
FROM Sessions
WHERE duration >= 900;
