如何编写SQL查询,获取对应列包含全部指定数据的id
查找包含所有指定names值的ID
假设我们有一张表(这里我暂时叫它target_table,你可以替换成实际的表名),数据如下:
+---------+------------+ | id | names | +---------+------------+ | 1 | a | | 1 | b | | 1 | c | | 1 | d | | 2 | b | | 3 | a | | 3 | b | | 3 | c | | 4 | c | +---------+------------+
我们的需求是找出所有id,要求这些id的names列里**同时包含"a"、"b"、"c"**三个值,最终结果应该是1和3。下面是几种实用的解法:
方法一:分组计数法(最通用直观)
这是最常用的方案,通过分组统计来验证是否包含所有目标值:
SELECT id FROM target_table WHERE names IN ('a', 'b', 'c') GROUP BY id HAVING COUNT(DISTINCT names) = 3;
解释:
WHERE子句先过滤掉和目标值无关的行(比如id=1的'd'),减少后续计算量;- 按
id分组后,COUNT(DISTINCT names)统计该分组下有多少个不同的目标值; - 当计数等于3时,说明这个id同时拥有'a'、'b'、'c'三个值。
如果你的表中id和names的组合不会重复(也就是同一个id不会有两行相同的names),可以去掉DISTINCT,直接用COUNT(names) = 3,效率会更高一点。
方法二:交集查询法(适合支持INTERSECT的数据库)
如果你的数据库支持INTERSECT语法(比如PostgreSQL、SQL Server、Oracle等),可以分别找出包含每个目标值的id,再取它们的交集:
SELECT id FROM target_table WHERE names = 'a' INTERSECT SELECT id FROM target_table WHERE names = 'b' INTERSECT SELECT id FROM target_table WHERE names = 'c';
解释:
每个子查询分别获取包含对应names值的id列表,INTERSECT会只保留同时出现在三个列表中的id,也就是同时满足三个条件的id。这种写法逻辑清晰,读起来很直观。
方法三:关联子查询法(兼容性最强)
如果你的数据库不支持INTERSECT,或者你需要更灵活的条件判断,可以用EXISTS子查询来验证每个id是否满足所有条件:
SELECT DISTINCT t.id FROM target_table t WHERE EXISTS (SELECT 1 FROM target_table WHERE id = t.id AND names = 'a') AND EXISTS (SELECT 1 FROM target_table WHERE id = t.id AND names = 'b') AND EXISTS (SELECT 1 FROM target_table WHERE id = t.id AND names = 'c');
解释:
- 外层查询遍历表中的每个id,
EXISTS子查询会检查当前id是否存在对应的names值; - 只有当三个
EXISTS条件都满足时,这个id才会被选中; DISTINCT用来去重,因为原表中一个id对应多行数据。
内容的提问来源于stack exchange,提问作者Mohammed Shirhaan
相关产品推荐
相关产品推荐

