如何用单条SQL查询获取满足多属性条件的唯一产品数据
实现目标产品筛选的单条SQL方案
你的问题在于原查询使用OR条件,只要产品满足任一匹配规则就会被返回——Old Car符合brand=toyota,Future Car符合color=red,所以两者都出现在结果里。要只保留Old Car,我们需要筛选出**满足brand=toyota且完全不匹配color=red**的产品,以下两种单条SQL方案都能实现:
方案一:使用子查询排除不符合条件的产品
这种方法先锁定符合brand=toyota的产品,再排除那些存在color=red属性的产品:
SELECT DISTINCT p.id, p.title FROM products p JOIN attribute_values av ON p.id = av.product_id JOIN attributes a ON av.attribute_id = a.id WHERE a.name = 'brand' AND av.value = 'toyota' AND p.id NOT IN ( SELECT product_id FROM attribute_values av2 JOIN attributes a2 ON av2.attribute_id = a2.id WHERE a2.name = 'color' AND av2.value = 'red' );
方案二:使用GROUP BY + HAVING统计匹配项
这种方法先获取所有符合任一条件的行,再通过分组统计确保产品只满足brand=toyota,且不满足color=red:
SELECT p.id, p.title FROM products p JOIN attribute_values av ON p.id = av.product_id JOIN attributes a ON av.attribute_id = a.id WHERE (a.name = 'brand' AND av.value = 'toyota') OR (a.name = 'color' AND av.value = 'red') GROUP BY p.id, p.title HAVING COUNT(CASE WHEN a.name = 'brand' AND av.value = 'toyota' THEN 1 END) = 1 AND COUNT(CASE WHEN a.name = 'color' AND av.value = 'red' THEN 1 END) = 0;
补充说明
- 方案一的
DISTINCT是为了避免同一产品因多属性匹配出现重复行(不过在你的数据里Old Car只有一条匹配行,不加也能得到正确结果,但加上更通用)。 - 方案二通过
CASE表达式精准统计每个条件的匹配次数,确保只保留完全符合需求的产品。
内容的提问来源于stack exchange,提问作者Jumper
相关产品推荐
相关产品推荐

