订阅更新

6 月和 7 月每月消费都满 100 的顾客

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

LeetCode 1511 · 按月汇总、每月都满足、年份过滤

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

面试怎么回答

先用日期区间限定 2020 年 6 月到 7 月,再按顾客分组,HAVING 里分别对 6 月和 7 月做条件求和,两个都 >= 100。「每个月都满足」要分别判断,不能用合计代替;日期过滤要带上年份。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

顾客表、产品表(单价)、订单表(产品、数量、日期)。找出在 2020 年 6 月和 7 月,每个月消费金额都不少于 100 的顾客。

表结构

  • Customers:customer_id(主键)、name、country
  • Product:product_id(主键)、description、price
  • Orders:order_id(主键)、customer_id、product_id、order_date、quantity

思路

先算每个顾客每个月的消费额(数量 × 单价),只保留 6、7 两个月;再要求两个月都满足 ≥ 100。可以先过滤出达标的(顾客, 月份),再要求每个顾客达标月份数为 2;也可以按顾客分组后用两个条件求和直接判断。原解法只按月份过滤,没有限定 2020 年,其他年份的 6、7 月订单也会被算进来。

参考解法

select customer_id,name
from Customers
where customer_id in
(select customer_id
    from
        (select customer_id, month(order_date) as month , sum(quantity*price) as total
        from Orders o left join Product p on o.product_id = p.product_id
        where month(order_date) = 6 or month(order_date)=7
        group by customer_id,month(order_date)
        ) as t1
    where total >=100
    group by customer_id
    having count(*)>=2
)

另一种写法:按顾客分组,两个月分别求和判断

SELECT c.customer_id, c.name
FROM Customers c
JOIN Orders o ON c.customer_id = o.customer_id
JOIN Product p ON o.product_id = p.product_id
WHERE o.order_date >= '2020-06-01' AND o.order_date < '2020-08-01'
GROUP BY c.customer_id, c.name
HAVING SUM(IF(MONTH(o.order_date) = 6, o.quantity * p.price, 0)) >= 100
   AND SUM(IF(MONTH(o.order_date) = 7, o.quantity * p.price, 0)) >= 100

易错点

  • 只写 MONTH(order_date) IN (6, 7) 会把其他年份的数据算进来。
  • 「每个月都满足」不能写成「两个月合计 ≥ 200」。
刷题进度保存在当前浏览器