SQL Server查询:筛选所有Id均在指定范围内的Input_Id
看起来你的需求描述和给出的例子有点小歧义哦!根据你说的「指定范围为(2,4,244,246,21)时,预期仅返回Input_Id=3」,你的真实需求应该是找出那些包含指定范围内所有Id的Input_Id(也就是指定范围里的每一个Id都能在该Input_Id的关联记录中找到)——毕竟Input_Id=3的关联Id里包含了这个范围的全部5个值,而Input_Id=2缺少244、246,Input_Id=4缺少21、244、246,所以只有3符合要求。如果是这个需求,我给你几个可行的实现方法:
方法1:GROUP BY + HAVING 统计匹配数量
这种方法适合指定范围元素不多的情况,核心是统计每个Input_Id匹配到的唯一目标Id数量,等于目标范围的总元素数就说明符合要求:
SELECT Input_Id FROM Test WHERE Id IN (2, 4, 244, 246, 21) GROUP BY Input_Id HAVING COUNT(DISTINCT Id) = 5 -- 这里的数字要和目标范围的唯一元素数量一致
方法2:多EXISTS子句逐一验证
如果目标范围的元素不多,这种写法逻辑更直观,直接检查每个目标Id都和当前Input_Id存在关联:
SELECT DISTINCT Input_Id FROM Test t WHERE EXISTS (SELECT 1 FROM Test WHERE Input_Id = t.Input_Id AND Id = 2) AND EXISTS (SELECT 1 FROM Test WHERE Input_Id = t.Input_Id AND Id = 4) AND EXISTS (SELECT 1 FROM Test WHERE Input_Id = t.Input_Id AND Id = 21) AND EXISTS (SELECT 1 FROM Test WHERE Input_Id = t.Input_Id AND Id = 244) AND EXISTS (SELECT 1 FROM Test WHERE Input_Id = t.Input_Id AND Id = 246)
方法3:用CTE + INTERSECT 匹配集合
如果目标范围的元素较多,可以先把目标Id放进一个临时CTE,再通过集合交集来判断:
WITH TargetIds AS ( SELECT 2 AS Id UNION ALL SELECT 4 UNION ALL SELECT 21 UNION ALL SELECT 244 UNION ALL SELECT 246 ) SELECT Input_Id FROM Test t GROUP BY Input_Id HAVING ( SELECT Id FROM Test WHERE Input_Id = t.Input_Id INTERSECT SELECT Id FROM TargetIds ) = (SELECT Id FROM TargetIds)
当然,如果你的需求确实是最初描述的「仅返回其所有关联Id都在指定范围内的Input_Id」(也就是Input_Id的任何一个Id都不能超出指定范围),那正确的查询应该排除那些存在超出范围Id的Input_Id:
SELECT DISTINCT Input_Id FROM Test t1 WHERE NOT EXISTS ( SELECT 1 FROM Test t2 WHERE t2.Input_Id = t1.Input_Id AND t2.Id NOT IN (2, 4, 244, 246, 21) )
或者用GROUP BY + HAVING的写法:
SELECT Input_Id FROM Test GROUP BY Input_Id HAVING COUNT(CASE WHEN Id NOT IN (2, 4, 244, 246, 21) THEN 1 END) = 0
这两个查询会返回Input_Id=2和4,因为它们的所有Id都在指定范围内,而Input_Id=3因为有Id=248不在范围内会被排除。
内容的提问来源于stack exchange,提问作者Azadeh Khobiyari
相关产品推荐
相关产品推荐

