我正在学习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和整个互联网上研究的问题不一定适合同样的问题。我非常感激您的专业知识和帮助。感谢您花时间阅读本文并在选择时提供帮助!
答案 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>
我帮助它并且不会让你太困惑:
让我们首先了解连接的作用(不使用任何SQL脚本),并且我们将更好地理解如何使用它。
说这是一个电影列表:
- 末日
- 蝙蝠侠
- 灰姑娘
醇>
和一系列类型:
- 动作
- 奇幻
- 西
醇>
当您加入两个表时,数据库会创建一个新表,对于movies
表中的每一行,您将获得genres
表中所有可能的行,如下所示:
- Armageddon&lt; - &gt;操作
- Armageddon&lt; - &gt;幻想
- Armageddon&lt; - &gt;西方
- 蝙蝠侠&lt; - &gt;行动
- 蝙蝠侠&lt; - &gt;幻想
- 蝙蝠侠&lt; - &gt;西方
- 灰姑娘&lt; - &gt;操作
- 灰姑娘&lt; - &gt;幻想
- 灰姑娘&lt; - &gt;西方
醇>
您还可以看到新表行号是3 * 3( [表1行号] 乘以 [表2行号] )。你能解释一下为什么吗?如果是这样,让我们继续我们的第二步......
在你的数据库中,你跟踪哪个类型的电影(通过它识别类型的id),所以让我们谈谈看起来像这样的新表,并获得有关电影类型的信息:
- 1 - Armageddon - 1
- 2 - Armageddon - 2
- 4 - 蝙蝠侠 - 1
- 5 - 蝙蝠侠 - 2
- 6 - 蝙蝠侠 - 3
- 7 - Cinderella - 2
醇>
该流派:
- 1 - 行动
- 2 - 幻想
- 3 - Western
醇>
正如我们刚刚解释的那样,加入两个表格会让你...... 18行(6 * 3 = 18。为什么?因为对于电影表格中的每一行,你都会得到所有可能的行流派表)。我不会写那18行,我希望你明白这一点......
每次调用联接时(无论哪种联接: LEFT / RIGHT / OUTER / INNER ),数据库都会创建一个包含所有可选选项的新表( [表1行号] 乘以 [表2行号] )。现在,您可能在想:数据库如何删除我不想要的行?
movies.genre_id = genres.id
(但不要丢弃任何未标记的行!!!)&#34;。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,所以暂时放弃它。)