SQL技术问询:如何筛选从未购买过500元商品的用户?
解决思路:筛选从未购买过500元商品的用户
嘿,这个问题我之前踩过坑!你的初始查询之所以达不到预期,是因为它只是返回了有非500元订单记录的用户,但这些用户很可能同时也买过500元的商品——咱们要的可是完全没碰过500元商品的用户对吧?
下面给你几种靠谱的调整方案,每种都带逻辑解释:
方案1:用NOT EXISTS(推荐,逻辑清晰且效率高)
这是最直观的写法,直接表达“不存在该用户的500元订单”这个逻辑:
SELECT u.* FROM users u WHERE NOT EXISTS ( -- 子查询:检查当前用户有没有500元的订单 SELECT 1 FROM purchases p WHERE p.userId = u.id AND p.price = 500 );
逻辑说明:遍历每个用户,只要在订单表里找不到任何一条属于该用户、价格为500的记录,就把这个用户选出来,完美匹配你的需求。
方案2:用LEFT JOIN + IS NULL
通过左连接筛选出没有匹配500元订单的用户:
SELECT DISTINCT u.* FROM users u LEFT JOIN purchases p ON u.id = p.userId AND p.price = 500 -- 只连接用户的500元订单 WHERE p.id IS NULL; -- 找不到对应500元订单的用户,p.id会是NULL
逻辑说明:左连接会保留所有用户,哪怕他们没有500元订单。那些从未买过500元商品的用户,对应的订单字段会是NULL,筛选出这些用户即可。加DISTINCT是为了避免用户有多个非500订单时重复返回。
方案3:用NOT IN
先找出所有买过500元商品的用户ID,再从用户表中排除这些ID:
SELECT * FROM users WHERE id NOT IN ( -- 子查询:获取所有买过500元商品的用户ID SELECT DISTINCT userId FROM purchases WHERE price = 500 );
逻辑说明:先拿到“买过500元商品”的用户集合,然后取用户表的补集,就是你要的目标用户。注意:如果purchases表的userId有NULL值,这个方法可能会出问题,所以确保userId是非空关联字段再用。
为什么你的初始查询不对?
你的初始语句select * from purchase p join user u on u.id = p.userId and price != 500是内连接,它只会返回那些有订单且订单价格不是500的用户行。但这些用户可能还有其他价格为500的订单,所以完全不符合“从未购买过500元商品”的要求哦。
内容的提问来源于stack exchange,提问作者Ricce
相关产品推荐
相关产品推荐

