订阅更新

会话时长分桶:空的桶也要显示 0

SQL 实战 123 题 · 第 108 题 简单 约 3 分钟读完

LeetCode 1435 · 分桶统计、维度表补零、CASE

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

分桶统计要补空桶,我会先构造包含所有桶名的小表,再 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>。
刷题进度保存在当前浏览器