我的数据库中有两个表:
表1(BonInterne):
+---------+
| num |
+---------+
|1 |
+---------+
|2 |
+---------+
|3 |
+---------+
|4 |
+---------+
表2(LigneBonInterne):
+---------+-----------+
|numOrdre |numBon |
+---------+-----------+
|20 |1 +
+---------+-----------+
|21 |2 |
+---------+-----------+
|22 |NULL +
+---------+-----------+
|23 |2 |
+---------+-----------+
|24 |1 +
+---------+-----------+
|25 |2 |
+---------+-----------+
|26 |NULL +
+---------+-----------+
|27 |1 |
+---------+-----------+
我想从表1中获取所有记录,其中num不在第二个表中,这是我尝试的scipt:
SELECT * FROM BonInterne WHERE num NOT IN (SELECT numBon FROM LigneBonInterne)
但是MySQL返回了一个空的结果集。
他应该返回如下:
+---------+
| num |
+---------+
|3 |
+---------+
|4 |
+---------+
我需要在查询中更改以获取该表吗?
答案 0 :(得分:2)
SQL 101
SELECT x.*
FROM x
LEFT
JOIN y
ON y.thing = x.thing
WHERE y.thing IS NULL;
答案 1 :(得分:2)
Select B.num
From BonInterne As B
Left Join LigneBonInterne As L
On L.numBon = B.num
Where L.numBon Is Null
原始查询无效的原因之一是LigneBonInterne
表包含numBon
列的空值。 In
函数转换为一系列Or
语句(例如Foo In(A,B,C)
等同于Foo = A Or Foo = B Or Foo = C
。对于Foo Not In(A,B,C)
,我们得到Foo <> A And Foo <> B And Foo <> C
。 )。因此,如果其中一个值为null,我们将得到null的比较,并返回false(技术上它返回Unknown)。
此SQL Fiddle example会显示您的原始查询,但请注意我为numBon
添加了空值,但未获得结果。拿出那个价值,我们就这样做了。
如果LigneBonInterne
中确实存在空值,则上述解决方案将起作用。另一种选择是使用In
函数,但过滤掉子查询中的空值
Select B.num
From BonInterne As B
Where Not In (
Select L1.numBon
From LigneBonInterne As L1
Where L1.numBon Is Not Null
)
另一种选择是使用Exists
代替In
:
Select B.num
From BonInterne As B
Where Not Exists (
Select 1
From LigneBonInterne As L1
Where L1.numBon = B.num
)
使用Exists
时,Select
子句完全被忽略。有些人使用Select *
,有些人使用Select Null
,有些人使用Select 1
。没关系;重要的是查询的其余部分是否返回行。这种类型的查询称为相关子查询,因为在内部查询中有一个引用外部查询(L1.numBon = B.num
)的列。
那么,你应该使用哪种形式?在这种情况下,可以通过三种形式中的任何一种来实现意图的清晰。但是,数据库产品在有效处理相关子查询的能力方面各不相同。在MySQL的情况下,它可能会通过左连接,然后是In函数和最后的Exists函数执行最佳。
答案 2 :(得分:2)
您的查询非常接近,您只需要包含一个where子句来过滤那些非空的值:
SELECT num
FROM BonInterne
WHERE num NOT IN (SELECT numBon
FROM LigneBonInterne
where numBon is not null);