SQL外部联接 - 执行不当

时间:2015-05-19 17:23:07

标签: mysql sql join left-join outer-join

我正在学习SQL,我已经学习了复数的基础课程,现在我通过Treehouse使用MySQL,他们通过MySQL服务器设置了虚拟数据库。一旦我的培训完成,我将每天在工作中使用SQLServer。

昨天我遇到了一个由两部分组成的挑战,我遇到了一些麻烦。 挑战中的第一个问题是:

  

“我们有一个'电影'表,其中包含'title'和'genre_id'列以及a   'genres'表,其中包含'id'和'name'列。使用INNER JOIN   加入'电影'和'流派'表一起只选择   电影'头衔'第一,流派'名字'第二。“

了解如何正确设置JOINS对我来说有点困惑,因为概念看起来很简单,但在烹饪中,执行就是一切 - 而且我做错了。我 能够在经过一些试验和错误,工作以及重复Treehouse解释几次之后想出这个。这是我如何通过树屋接受的答案解决第一个问题:

SELECT movies.title, genres.name FROM movies INNER JOIN genres ON movies.genre_id = genres.id;

- BUT -

接下来的挑战问题我没有那么成功,而且我不确定我哪里出错了。我真的希望通过JOINS变得更好,挑选所有聪明人的大脑是我能想到的最好的方法来解释这个特定的(我确定,对你们来说很可怜)问题。谢谢你的帮助,这里是我难倒的地方:

  

“像之前一样,带回电影'标题'和流派'名字',但使用   正确的OUTER JOIN带回所有电影,无论是否   “genre_id”是否设定。“

这是我提出的最接近(?)的解决方案,但我在这里做错了(可能很多)错误:

SELECT movies.title, genres.name FROM movies LEFT OUTER JOIN genres ON genres.id;

我最初尝试了这个(下面),但是当它不起作用时,我决定删除声明的最后部分,因为在需求标准中提到我需要一个不关心genre_id的数据集是否在电影表中设置:

SELECT movies.title, genres.name FROM movies LEFT OUTER JOIN genres ON movies.genre_id = genres.id;

我知道这是 noob的东西,但就像我说的那样,我正在学习,我在Stack和整个互联网上研究的问题不一定适合同样的问题。我非常感激您的专业知识和帮助。感谢您花时间阅读本文并在选择时提供帮助!

2 个答案:

答案 0 :(得分:2)

您的解决方案是正确的:

SELECT movies.title, genres.name 
    FROM movies 
        LEFT OUTER JOIN genres ON movies.genre_id = genres.id

这是我的解释:

当您告诉“左连接”或“左外连接”时,事实上,

  

不是“您不关心是否在电影表格中设置了genre_id”,

     

但是“你想要显示每部电影的所有类型,但是,你不关心是否在电影表中为某些记录设置了genre_id;只是在这些情况下显示电影[并显示'genre = NULL '对于那些记录'“

通常,在“左连接”中,您需要:

  

左表的所有记录,以及其他表中的相应记录(如果有)。否则为NULL。

在您的示例中,将显示以下两组记录:

  

1-所有已设置为流派的电影
  (给movie.title,Genres.name)

     

2-所有其他电影[没有类型,即genre_id = NULL]
  (给movie.title,NULL)

示例(左连接):

Title, Genre
--------------
Movie1, Comedy
Movie1, Dramma
Movie1, Family
Movie2, NULL
Movie3, Comedy
Movie3, Dramma
Movie4, Comedy
Movie5, NULL

示例(使用内部联接):

Title, Genre
--------------
Movie1, Comedy
Movie1, Dramma
Movie1, Family
Movie3, Comedy
Movie3, Dramma
Movie4, Comedy

答案 1 :(得分:2)

但您的具体问题已经得到解答:

我想添加另一个关于JOIN的观点,我认为这将有助于您了解将来如何使用它(之后,我还建议您关注此链接:SQL JOINS)。< / p>

这个观点来自DB眼睛,这是&#34; dumb&#34;并且无法猜出你真正希望它为你做什么。

我帮助它并且不会让你太困惑:

让我们首先了解连接的作用(不使用任何SQL脚本),并且我们将更好地理解如何使用它。

说这是一个电影列表:

  
      
  1. 末日
  2.   
  3. 蝙蝠侠
  4.   
  5. 灰姑娘
  6.   

和一系列类型:

  
      
  1. 动作
  2.   
  3. 奇幻
  4.   
  5. 西
  6.   

当您加入两个表时,数据库会创建一个新表,对于movies表中的每一行,您将获得genres表中所有可能的行,如下所示:

  
      
  1. Armageddon&lt; - &gt;操作
  2.   
  3. Armageddon&lt; - &gt;幻想
  4.   
  5. Armageddon&lt; - &gt;西方
  6.   
  7. 蝙蝠侠&lt; - &gt;行动
  8.   
  9. 蝙蝠侠&lt; - &gt;幻想
  10.   
  11. 蝙蝠侠&lt; - &gt;西方
  12.   
  13. 灰姑娘&lt; - &gt;操作
  14.   
  15. 灰姑娘&lt; - &gt;幻想
  16.   
  17. 灰姑娘&lt; - &gt;西方
  18.   

您还可以看到新表行号是3 * 3( [表1行号] 乘以 [表2行号] )。你能解释一下为什么吗?如果是这样,让我们​​继续我们的第二步......

在你的数据库中,你跟踪哪个类型的电影(通过它识别类型的id),所以让我们谈谈看起来像这样的新表,并获得有关电影类型的信息:

  
      
  1. 1 - Armageddon - 1
  2.   
  3. 2 - Armageddon - 2
  4.   
  5. 4 - 蝙蝠侠 - 1
  6.   
  7. 5 - 蝙蝠侠 - 2
  8.   
  9. 6 - 蝙蝠侠 - 3
  10.   
  11. 7 - Cinderella - 2
  12.   

该流派:

  
      
  1. 1 - 行动
  2.   
  3. 2 - 幻想
  4.   
  5. 3 - Western
  6.   

正如我们刚刚解释的那样,加入两个表格会让你...... 18行(6 * 3 = 18。为什么?因为对于电影表格中的每一行,你都会得到所有可能的行流派表)。我不会写那18行,我希望你明白这一点......

每次调用联接时(无论哪种联接: LEFT / RIGHT / OUTER / INNER ),数据库都会创建一个包含所有可选选项的新表( [表1行号] 乘以 [表2行号] )。现在,您可能在想:数据库如何删除我不想要的行?

  1. 首先,您定义一个ON条件。你告诉你的数据库:&#34;请为我标记符合我条件的所有行:movies.genre_id = genres.id(但不要丢弃任何未标记的行!!!)&#34;。
  2. 其次,你告诉你的数据库你要删除哪种行(或编辑!!!):现在来了JOIN类,这有点棘手。
  3. INNER JOIN 很容易理解 - 只需告诉数据库:&#34;删除所有不符合条件的行:{{1} }&#34; (当然,在您放弃我不需要的这些行之后,向我显示更新的表格。)

    LEFT / RIGHT JOIN 更复杂。让我们以 LEFT JOIN 为例。你告诉你的数据库:&#34;好吧,如果一行不符合我的条件:movies.genre_id = genres.id,请标记我的行的右边部分(意思是代表我的第二行的列) table)as null,并且离开了。 这样,我知道table1中的这一行,在table2中没有匹配的行。

    RIGHT JOIN 中,情况恰恰相反:您告诉数据库,如果您的条件未满足,请在左侧标记空。

    FULL JOIN 告诉您的数据库:&#34;好吧,从不符合条件的行中,制作2行:1行有& #39; s RIGHT部分标记为null,第二部分标记为null&#34; (这有点复杂,因为你理解为什么你需要这样做,并且你在第一步中几乎不需要使用FULL JOIN,所以暂时放弃它。)

    总之,我在您设计JOIN查询时的建议

    1. 首先,了解您想要的内容,请参阅答案中的插图:SQL JOINS
    2. 然后,当您需要向DB解释它应该做什么时,会出现该部分:
      • 首先,告诉它应该标记哪些行,
      • ,告诉它应删除/编辑哪些行。
相关问题