如何用SQL筛选拥有指定全部属性的对象?
筛选同时拥有指定属性集合的对象SQL实现
问题原因分析
你之前的SQL语句无法得到预期结果的原因:
- 使用
AND时,要求同一行的a.description同时等于两个不同值,单条记录不可能满足,因此返回空结果。 - 使用
OR时,只要对象拥有其中一个属性就会被选中,不符合“同时拥有所有指定属性”的需求。
解决方案
以下几种SQL写法可直接实现需求,无需后续代码过滤:
方法1:GROUP BY + HAVING(推荐,适配多属性场景)
通过分组统计对象拥有的指定属性数量,判断是否覆盖所有目标属性:
SELECT o.name FROM link l INNER JOIN object o ON o.id = l.o_id INNER JOIN attr a ON a.id = l.a_id WHERE a.description IN ('attr0', 'attr1') GROUP BY o.id, o.name HAVING COUNT(DISTINCT a.description) = 2;
- 说明:
IN筛选出所有包含目标属性的记录,按对象分组后,COUNT(DISTINCT)统计该对象拥有的不同目标属性数量,等于目标属性总数(此处为2)即表示同时拥有所有属性。若同一对象不会重复关联同一属性,可简化为COUNT(*)。
方法2:多次JOIN(适配少量属性场景)
为每个目标属性单独关联关联表和属性表,确保对象同时存在所有属性的关联记录:
SELECT o.name FROM object o INNER JOIN link l1 ON o.id = l1.o_id INNER JOIN attr a1 ON l1.a_id = a1.id AND a1.description = 'attr0' INNER JOIN link l2 ON o.id = l2.o_id INNER JOIN attr a2 ON l2.a_id = a2.id AND a2.description = 'attr1';
- 说明:每个属性对应一次
JOIN,只有同时满足所有属性关联条件的对象才会被保留。
方法3:EXISTS子查询(逻辑直观)
通过多个EXISTS子查询分别验证对象是否拥有每个目标属性:
SELECT o.name FROM object o WHERE EXISTS ( SELECT 1 FROM link l JOIN attr a ON l.a_id = a.id WHERE l.o_id = o.id AND a.description = 'attr0' ) AND EXISTS ( SELECT 1 FROM link l JOIN attr a ON l.a_id = a.id WHERE l.o_id = o.id AND a.description = 'attr1' );
- 说明:每个
EXISTS检查对象是否存在对应属性的关联记录,只有所有检查通过的对象才会被选中。
内容的提问来源于stack exchange,提问作者Werdck
相关产品推荐
相关产品推荐

