左外连接不起作用

Posted

技术标签:

【中文标题】左外连接不起作用【英文标题】:LEFT OUTER JOIN does not work 【发布时间】:2015-03-03 16:06:21 【问题描述】:

早安,

我正在进行 SQL 学习之旅,并尝试创建一个包含一些查询的小型数据库来获得经验。 使用的两个数据库,Person id, name, age 和 Knows id, guest1_id → Persons, guest2_id → Persons

查询应生成一个不认识数据库中任何人但可以被其他人认识的人的姓名列表。以下是我目前得到的代码,但它似乎没有获得任何东西。

这里有什么问题?

SELECT distinct K.id
FROM Persons P 
LEFT JOIN Knows K
ON K.guest1_id = P.id 
AND K.guest2_id = P.id
WHERE K.id NOT IN (
    SELECT id
    FROM Knows )

谢谢!

【问题讨论】:

您只要求Knows 的行,其中:a)guest1 是某个人并且 b)guest2 是同一个人。这听起来不像你想要的……?我会尽快输入建议的解决方案 wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN 【参考方案1】:

您的问题没有意义,查询的外观也没有意义。但是,如果您要查找所有不认识任何人的人,那么总而言之,这意味着该人既不在 Knows 表中的 guest1 或 guest2 ID 列中。

如果是这种情况,您可以对 know 表进行双左连接,然后只获取那些不适合任何一方的表

SELECT 
      P.*
   from 
      Persons P 
      LEFT JOIN Knows K1
         on P.id = K1.guest1
      LEFT JOIN Knows K2
         on P.id = K2.guest2
   where
          K1.guest1 IS NULL
      AND K2.guest2 IS NULL

所以如果你的表

Persons
ID  Name
1   A
2   B
3   C
4   D

and Knows table
ID  Guest1   Guest2
1   1        3
2   1        4
3   3        4 

那么人 2 是唯一不认识其他人的人,因此他们的 ID 不在 Knows 表的 Guest1 或 Guest2 列中。

【讨论】:

您的回答对我来说似乎合乎逻辑,但是,它给我的 SQL 语法错误。我知道这是非常基本的,但我似乎找不到语法错误。 @Ypan,我有 Person.* 而不仅仅是别名 P.* 查询找不到“Person”表引用,因为它是“PersonS”表或别名“P”。此外,您作为解决方案检查的另一个答案将失败,因为它永远不会测试处于第二位置的人。【参考方案2】:

试试这个:

SELECT P.*
FROM Persons P 
LEFT JOIN Knows K ON K.guest1_id = P.id
WHERE K.id IS NULL

这会给你Persons 不认识的人。

你也可以试试这个:

SELECT *
FROM Persons
WHERE NOT EXISTS(SELECT 1 FROM Knows WHERE guest1_id = P.id)

【讨论】:

我明白你的意思了,但是不认识任何人的人仍然可以被其他人认识。我应该将 K.id IS NULL 更改为其中任何一个 IS NULL 吗?或者这不是解决方案? 我编辑了两个查询以反映这一点。我刚刚删除了对 guest2_id 的任何引用【参考方案3】:
WHERE K.id NOT IN (SELECT id FROM Knows)

这个 where 子句本质上排除了所有数据条目,K.id 必须在 Knows 的 ids 中。

【讨论】:

【参考方案4】:

where 子句中的条件有点傻:

...  K.id NOT IN (SELECT id
                 FROM Knows)

K 是 Knows 的别名,所以基本上这就是说:“只选择不存在的行”。

此外,此条件不适用于 NULL 值。我认为你试图做的实际上是这样的:

SELECT P.id
FROM Persons P 
  WHERE NOT EXISTS(
     SELECT * FROM Knows K WHERE 
        K.guest1_id = P.id OR
        K.guest2_id = P.id)

此查询表示:“选择所有未在 guest1 字段和/或 'Knows' 的 guest2 字段中提及的人员。

您也可以使用 LEFT JOIN 和 where 子句中的 K.id IS NULL 来编写它。这更接近您的尝试,但对问题的语义不太准确,因此在我看来不是首选。

SELECT distinct K.id
FROM Persons P 
LEFT JOIN Knows K ON K.guest1_id = P.id OR K.guest2_id = P.id
WHERE K.id IS NULL

【讨论】:

以上是关于左外连接不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 hive 中使用 Null 检查的左外连接查询不起作用

在 Linq 中使用左外连接

socket.io 连接事件不起作用,为啥?

检查 Internet 连接不起作用

连接移动数据时 Ajax 不起作用

我的 pdo 连接不起作用