销售分析三:只在 2019 年春季卖过的产品
LeetCode 1084 · 「全部满足」判断、MIN/MAX 区间
面试怎么回答
按产品分组,HAVING MIN(sale_date) >= '2019-01-01' AND MAX(sale_date) <= '2019-03-31'。「全部满足」用最小最大值卡住区间最直接;如果用排除法,要注意没卖过的产品会被误算进来。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
找出所有销售都发生在 2019 年 1 月 1 日到 3 月 31 日之间的产品,输出产品 ID 和名称。
表结构
- Product:product_id(主键)、product_name、unit_price
- Sales:seller_id、product_id、buyer_id、sale_date、quantity、price
思路
「所有销售都在区间内」等价于「最早的销售不早于起点,最晚的销售不晚于终点」,按产品分组后用 MIN 和 MAX 判断最简洁。也可以用「区间内的销售数 = 总销售数」。原文还有一种 NOT IN 写法(排除在区间外卖过的产品),但它会把从没卖过的产品也算进来。
参考解法
写法 1:区间内销售数等于总销售数
select product_id, product_name
from Sales join Product
using(product_id)
group by product_id
having sum(sale_date between "2019-01-01" and "2019-03-31") = count(sale_date)
写法 2:最早和最晚销售日期都落在区间内
select p.product_id, p.product_name
from sales s, product p
where s.product_id = p.product_id
group by s.product_id
having min(s.sale_date)>='2019-01-01' and max(s.sale_date) <= '2019-03-31'
易错点
- 用产品表 NOT IN「区间外卖过的产品」,从没卖过的产品也会被返回,不符合「春季卖过」的要求。
- 日期是字符串比较时,格式必须统一为 YYYY-MM-DD。