带OR条件的SQL子查询编写:筛选符合指定品牌持有规则的用户名
原SQL的问题
- 子查询中的
where brand = 'Iphone' and brand = 'Samsung'是矛盾条件,同一行记录的brand字段不可能同时等于两个不同值,所以这个子查询永远返回空结果,OR后面的条件等于完全失效,你写的SQL实际只会返回所有持有过Iphone的用户,完全没有做「无其他品牌」「仅持有指定组合」的判断。 - 你的需求是基于用户维度的聚合统计结果筛选,不能直接基于单行数据判断,必须先按姓名分组后做聚合校验。
正确SQL写法
思路是按Name分组后,通过聚合函数校验两个条件:
- 该用户持有的所有品牌都在
Iphone、Samsung范围内,没有其他品牌 - 该用户必须持有
Iphone(两种符合要求的场景都包含Iphone)
通用标准SQL写法(所有数据库兼容)
SELECT Name FROM 你的表名 GROUP BY Name HAVING -- 校验无Iphone、Samsung之外的其他品牌 COUNT(DISTINCT CASE WHEN Brand NOT IN ('Iphone', 'Samsung') THEN Brand END) = 0 AND -- 校验必须持有Iphone SUM(CASE WHEN Brand = 'Iphone' THEN 1 ELSE 0 END) >= 1
简化写法(不同数据库语法略有差异)
如果你的数据库支持集合聚合函数,可以用更直观的写法:
-- Spark SQL/ Hive 写法 SELECT Name FROM 你的表名 GROUP BY Name HAVING COLLECT_SET(Brand) IN (array('Iphone'), array('Iphone', 'Samsung'))
-- PostgreSQL写法 SELECT Name FROM 你的表名 GROUP BY Name HAVING ARRAY_AGG(DISTINCT Brand ORDER BY Brand) IN (ARRAY['Iphone'], ARRAY['Iphone', 'Samsung'])
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

