MySQL LEFT JOIN 3 个表

Posted

技术标签:

【中文标题】MySQL LEFT JOIN 3 个表【英文标题】:MySQL LEFT JOIN 3 tables 【发布时间】:2013-04-19 18:45:03 【问题描述】:

我有 3 张桌子:

人员(PersonID、姓名、SS)
恐惧(FearID,恐惧)
Person_Fear(ID、PersonID、FearID)

现在我想列出每个人都有任何与他们相关的恐惧(可以是多种恐惧,但也可以没有)。即使一个人没有与他们相关的恐惧,也必须显示 people 表。

我认为我需要进行 LEFT JOIN,但我的代码似乎不起作用:

SELECT persons.name, 
       persons.ss, 
       fears.fear 
FROM   persons 
       LEFT JOIN fears 
              ON person_fear.personid = person_fear.fearid 

我在这里做错了什么?

【问题讨论】:

你试过我的解决方案了吗? 【参考方案1】:
SELECT p.*, f.Fear
FROM Persons p
LEFT JOIN Person_Fear pf ON pf.PersonID = p.PersonID
LEFT JOIN Fears f ON f.FearID = pf.FearID
ORDER BY p.PersonID

    您需要从Persons 表中进行选择,以确保为每个人生成一行,无论他们是否有恐惧。 然后,您可以将加入 Person_Fear 留给每个人,如果他们没有任何条目(如您所愿),则为 NULL。 最后,您在Person_Fear 上离开了加入Fears,以便您可以选择恐惧的名称。 (可选)添加一个订单,以便将每个人的所有恐惧都列在一起,即使他们是在不同时间添加到 Person_Fear 表中的。

【讨论】:

【参考方案2】:
Select Persons.Name, Persons.SS, Fears.Fear
From Persons
LEFT JOIN Persons_Fear
ON Persons.PersonID = Person_Fear.PersonID
LEFT JOIN Fears
ON Person_Fear.FearID = Fears.FearID;

【讨论】:

不鼓励使用纯代码的答案。请描述此代码在 OP 未实现的情况下做了什么。 这是一个非常实用的答案。你们应该停止劝阻新手。如果你发现它太代码,你自己添加一些 cmets-y【参考方案3】:

试试这个绝对有效。

SELECT p.PersonID AS person_id,
   p.Name, p.SS, 
   f.FearID AS fear_id,
   f.Fear 
   FROM person_fear AS pf 
      LEFT JOIN persons AS p ON pf.PersonID = p.PersonID 
      LEFT JOIN fears AS f ON pf.PersonID = f.FearID 
   WHERE f.FearID = pf.FearID AND p.PersonID = pf.PersonID

【讨论】:

我无法让它工作,但我通过删除 AS 变量并仅使用完整的表名解决了这个问题 任何人都可以评论左,左连接与左,内连接之间的性能差异【参考方案4】:

您正试图将Person_Fear.PersonID 加入Person_Fear.FearID - 这真的没有意义。你可能想要这样的东西:

SELECT Persons.Name, Persons.SS, Fears.Fear FROM Persons
LEFT JOIN Person_Fear
    INNER JOIN Fears
    ON Person_Fear.FearID = Fears.FearID
ON Person_Fear.PersonID = Persons.PersonID

这通过中间表Person_FearPersons 连接到Fears。因为PersonsPerson_Fear 之间的连接是LEFT JOIN,所以您将获得所有Persons 记录。

或者:

SELECT Persons.Name, Persons.SS, Fears.Fear FROM Persons
LEFT JOIN Person_Fear ON Person_Fear.PersonID = Persons.PersonID
LEFT JOIN Fears ON Person_Fear.FearID = Fears.FearID

【讨论】:

我投了反对票,因为您的原始帖子没有引用所有 3 个表格。您已经纠正了这一点,但是您的 On 子句的嵌套错误。 +1 - 我知道,这看起来是迄今为止唯一正确的答案(至少在任何编辑之后)。 顺便说一句,我不确定哪一个会更有效。我会打赌后者,因为如果没有PersonPerson_Fear 的关系,它就不需要将Person_Fear 的行加入Fears。谁能提供见解? @AntP 在我看来,当您开始提出这样的问题时,您就是在钻研过早优化的范畴。把你的索引整理好,不要像那样担心细节。一个体面的查询优化器可能会为每个查询计划生成一个非常相似的查询计划。 @Aheho:实际上,没有。 @AntP 是正确的,这是一个很好的问题。许多优化器会产生不同的查询计划。一个原因是查询在逻辑上并不相同。 (好的,但前提是存在从Person_FearFear 的FK)。 mysql 的原始优化器可能不知道并使用该信息。【参考方案5】:
Select 
    p.Name,
    p.SS,
    f.fear
From
    Persons p
left join
        Person_Fear pf
    inner join
        Fears f
    on
        pf.fearID = f.fearID
 on
    p.personID = pf.PersonID

【讨论】:

【参考方案6】:

试试这个

    SELECT p.Name, p.SS, f.Fear 
    FROM Persons p 
    LEFT JOIN Person_Fear fp 
    ON p.PersonID = fp.PersonID
    LEFT JOIN Fear f
    ON f.FearID = fp.FearID

【讨论】:

以上是关于MySQL LEFT JOIN 3 个表的主要内容,如果未能解决你的问题,请参考以下文章

MySQL LEFT JOIN 在第二个表中具有可选值

Mysql sum distinct 基于包含多个 LEFT JOIN 的其他列

MySQL:LEFT JOIN .. 从表 1 中选择所有,即使表 2 中没有?

mysql中left join和union有啥区别?

MySQL LEFT JOIN 或 WHERE IN SUBQUERY

Mysql LEFT JOIN GROUP BY LAST 每个表的记录