3

我的数据库中有两个表:

表 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        |
+---------+

我必须在查询中更改什么才能获得该表?

4

3 回答 3

2

SQL 101

SELECT x.* 
  FROM x
  LEFT
  JOIN y
    ON y.thing = x.thing
 WHERE y.thing IS NULL;
于 2013-06-07T15:53:55.340 回答
2
Select B.num
From BonInterne As B
    Left Join LigneBonInterne As L
        On L.numBon = B.num
Where L.numBon Is Null  

SQL 小提琴版本

连接的视觉解释

原始查询为什么不起作用的一种解释是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 示例显示了您的原始查询,但请注意,我为它添加了一个空值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 函数。

于 2013-06-07T15:54:58.933 回答
2

您的查询非常接近,您只需要包含一个 where 子句来过滤那些不为空的值:

SELECT num
FROM BonInterne 
WHERE num NOT IN (SELECT numBon 
                  FROM LigneBonInterne
                  where numBon is not null);

请参阅带有演示的 SQL Fiddle

于 2013-06-07T16:13:32.337 回答