LeetCode MySQL题:2021年订阅未播放的账号数统计及代码纠错
SQL问题排查:2021年订阅无播放账号统计
表结构说明
- Subscriptions表(订阅表):
| Column Name | Type |
|---|---|
| account_id | int |
| start_date | date |
| end_date | date |
account_id为表主键,每行记录对应一个账号的订阅起止日期,满足start_date < end_date规则。
- Streams表(播放会话表):
| Column Name | Type |
|---|---|
| session_id | int |
| account_id | int |
| stream_date | date |
session_id为表主键,account_id为关联Subscriptions表的外键,每行记录对应一个账号的一次流媒体播放会话及对应日期。
需求说明
统计2021年购买订阅、但全年没有任何流媒体播放会话的账号总数,要求使用精确日期匹配而非year=2021的判断逻辑。
现有代码问题梳理
你提供的原始代码如下:
with temp1 as ( select account_id from Subscriptions sb where start_date >= 2021-01-01 and end_date <= 2021-12-31 and account_id not in (select distinct(account_id) from streams where stream_date >= 2021-01-01 and stream_date <= 2021-12-31 )) select count(account_id) as accounts_count from temp1;
存在两个核心问题:
- 日期值缺少引号,逻辑完全错误:
2021-01-01这类日期值没有用单引号包裹时,SQL会将其识别为算术表达式,计算为2021-1-1=2019的数值,和日期字段对比时会出现类型不匹配或者筛选逻辑完全失效的问题,所有日期常量都需要用单引号包裹,写成'2021-01-01'、'2021-12-31'。 - 订阅范围筛选不符合需求:你添加了
end_date <= '2021-12-31'的限制,会把2021年购买、但订阅到期时间在2022年及以后的账号排除,不符合“2021年购买订阅”的统计要求:- 如果需求是统计2021年新购买订阅的账号,仅需要保留
start_date BETWEEN '2021-01-01' AND '2021-12-31'的条件,不需要限制end_date; - 如果需求是统计2021年全年有有效订阅的账号(含之前购买但2021年仍在有效期的),则需要改为
start_date <= '2021-12-31' AND end_date >= '2021-01-01'。
- 如果需求是统计2021年新购买订阅的账号,仅需要保留
修正后代码
以统计2021年新购买订阅的账号为例,修正后代码如下:
WITH temp1 AS ( SELECT account_id FROM Subscriptions sb WHERE start_date >= '2021-01-01' AND start_date <= '2021-12-31' AND account_id NOT IN ( SELECT DISTINCT account_id FROM streams WHERE stream_date >= '2021-01-01' AND stream_date <= '2021-12-31' ) ) SELECT COUNT(account_id) AS accounts_count FROM temp1;
如果担心NOT IN遇到子查询返回NULL时逻辑失效的问题,可以改用NOT EXISTS写法:
SELECT COUNT(DISTINCT sb.account_id) AS accounts_count FROM Subscriptions sb WHERE sb.start_date >= '2021-01-01' AND sb.start_date <= '2021-12-31' AND NOT EXISTS ( SELECT 1 FROM streams s WHERE s.account_id = sb.account_id AND s.stream_date >= '2021-01-01' AND s.stream_date <= '2021-12-31' );
内容的提问来源于stack exchange,提问作者Ashima
相关产品推荐
相关产品推荐

