买下了所有产品的客户:关系除法
LeetCode 1045 · 关系除法、COUNT DISTINCT 与总数比较
面试怎么回答
这是关系除法。我按客户分组,HAVING COUNT(DISTINCT product_key) = (SELECT COUNT(*) FROM Product)。要提一句前提:购买记录里的产品都在产品表里;否则要先 JOIN 产品表过滤,再做计数比较。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
客户购买表记录客户买过的产品,产品表是全部产品清单。找出买过产品表中所有产品的客户 ID。
表结构
- Customer:customer_id、product_key(可能重复)
- Product:product_key(主键)
思路
「买全了所有产品」在关系代数里叫除法。最实用的写法是计数比较:每个客户买过的不同产品数,等于产品总数,就说明全买了。前提是客户买的产品都在产品表里(题目保证了外键关系)。
参考解法
select customer_id
from Customer
group by customer_id
having count(distinct product_key)=(
select count(*) cnt
from Product)
易错点
- 用 COUNT(*) 而不是 COUNT(DISTINCT product_key),重复购买会让计数虚高。
- 如果购买记录里可能有产品表之外的产品,要先关联产品表再计数,否则可能「数量对上但不是同一批产品」。