会话时长分桶:空的桶也要显示 0
LeetCode 1435 · 分桶统计、维度表补零、CASE
面试怎么回答
分桶统计要补空桶,我会先构造包含所有桶名的小表,再 LEFT JOIN 用 CASE 打好桶标签的明细,COUNT(明细列) 计数,空桶得到 0。这和补齐日期、补齐档位是同一个思路:先有完整的维度,再关联事实。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
会话表记录每次会话的时长(秒)。按 [0,5)、[5,10)、[10,15) 分钟和 15 分钟以上四个区间统计会话数,没有会话的区间也要输出 0。
表结构
- Sessions:session_id(主键)、duration(秒)
思路
直接用 CASE 分桶再 GROUP BY,空桶不会出现。要补零,有两种办法:一是每个桶写一条计数查询再 UNION ALL(COUNT 在没有匹配行时返回 0);二是先构造一张包含四个桶名的小表,再 LEFT JOIN 分桶结果计数。第二种更通用,桶多时不用写一堆 UNION。
参考解法
写法 1:每个桶一条计数查询拼起来
select '[0-5>' as bin, count(*) as total from Sessions where duration/60>=0 and duration/60<5
union
select '[5-10>' as bin, count(*) as total from Sessions where duration/60>=5 and duration/60<10
union
select '[10-15>' as bin, count(*) as total from Sessions where duration/60>=10 and duration/60<15
union
select '15 or more'as bin, count(*) as total from Sessions where duration/60>=15
写法 2:桶名维度表 LEFT JOIN 分桶结果
select a.bin, count(b.bin) as total
from
(
select '[0-5>' as bin union select '[5-10>' as bin union select '[10-15>' as bin union select '15 or more' as bin
)a
left join
(
select case
when duration < 300 then '[0-5>'
when duration >= 300 and duration < 600 then '[5-10>'
when duration >= 600 and duration < 900 then '[10-15>'
else '15 or more'
end bin
from Sessions
)b
on a.bin = b.bin
group by a.bin
易错点
- 只做 CASE + GROUP BY,空桶会消失。
- 区间边界要左闭右开,300 秒属于 [5-10>。