如何确定哪些“食物”没有关联的“酒吧”

时间:2013-10-07 17:35:04

标签: sql sql-server

我想找到所有没有关联Foos的{​​{1}}。

这是我正在使用的查询。它没有返回任何记录:

Bars

但是,我知道select * from foos f where f.id not in(select b.foo_id from bars b); foo没有关联的with id = 1583,因此我之前的查询中至少应该有一个结果。

有人可以指出我犯的错误吗?感谢。

2 个答案:

答案 0 :(得分:1)

看起来不错;如果是我,我会怀疑错字。你检查了数据吗?

 SELECT * from foos WHERE foos.id = 1583;
 SELECT * from bars WHERE bars.foo_id = 1583;

我假设您已从原文中重新创建声明以删除实际的表名 - 因此请校对您的实际查询。

或尝试加入语法:

 SELECT * FROM foos LEFT JOIN bars on foos.id = bars.foo_id WHERE bars.foo_id IS NULL;

答案 1 :(得分:1)

原因是SQL three valued logic

示例:两个语句都会显示'?'。

SELECT CASE WHEN 2 NOT IN (3,4,NULL) THEN 'True' ELSE '?' END AS Test#0
SELECT CASE WHEN 2 <> 3 AND 2 <> 4 AND 2 <> NULL THEN 'True' ELSE '?' END AS Test#0
--                TRUE  AND  TRUE  AND UNKNOWN => UNKNOWN (ELSE -> ?)

解决方案是使用NOT EXISTS而不是NOT IN:

DECLARE @foo TABLE(foo_id INT);
INSERT  @foo(foo_id)
SELECT 1 UNION ALL SELECT 2;

DECLARE @bars TABLE(bars_id INT IDENTITY(2,2), foo_id INT);
INSERT  @bars(foo_id)
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT NULL;

PRINT '@foo >'
SELECT * FROM @foo
PRINT '@bars >'
SELECT * FROM @bars

PRINT 'Test #1 >'
SELECT  *
FROM    @foo AS f
WHERE   f.foo_id NOT IN (SELECT b.foo_id FROM @bars AS b)

PRINT 'Test #2 >'
SELECT  *
FROM    @foo AS f
WHERE   NOT EXISTS (SELECT b.foo_id FROM @bars AS b WHERE b.foo_id = f.foo_id)

结果:

@foo >
foo_id
-----------
1
2

@bars >
bars_id     foo_id
----------- -----------
2           3
4           4
6           NULL

Test #1 >
foo_id
-----------

Test #2 >
foo_id
-----------
1
2