三个表的Mysql LEFT JOIN返回多行

时间:2012-03-23 14:04:31

标签: mysql sql database left-join

我使用Mysql已经有一段时间了,我对三张桌子上的简单LEFT JOIN的结果感到很困惑。

我有以下三个表(我创建了一个示例,以缩小范围)

a)人

+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| PersonID | int(11)     | NO   | PRI | NULL    | auto_increment |
| Name     | varchar(50) | YES  |     | NULL    |                |
| Age      | int(11)     | YES  |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+

b)person_fav_artists

+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| FavInterpretID | int(10)      | NO   | PRI | NULL    | auto_increment |
| PersonID       | int(10)      | NO   |     | 0       |                |
| Interpret      | varchar(100) | YES  |     | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+

c)person_fav_movies

+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| FavMovieID | int(10)      | NO   | PRI | NULL    | auto_increment |
| PersonID   | int(10)      | NO   |     | 0       |                |
| Movie      | varchar(100) | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

我的示例表用于将任意数量的艺术家和电影存储到一个人。 天气这种意义与否并不重要,因为它只是一个简单的例子。

现在我在表格中有以下数据:

mysql> SELECT * FROM persons;
+----------+------+------+
| PersonID | Name | Age  |
+----------+------+------+
|        1 | Jeff |   22 |
|        2 | Lisa |   15 |
|        3 | Jon  |   30 |
+----------+------+------+

mysql> SELECT * FROM person_fav_artists;
+----------------+----------+----------------+
| FavInterpretID | PersonID | Interpret      |
+----------------+----------+----------------+
|              1 |        1 | Linkin Park    |
|              2 |        1 | Muse           |
|              3 |        2 | Madonna        |
|              4 |        2 | Katy Perry     |
|              5 |        2 | Britney Spears |
|              6 |        1 | Fort Minor     |
|              7 |        1 | Jay Z          |
+----------------+----------+----------------+

mysql> SELECT * FROM person_fav_movies;
+------------+----------+-------------------+
| FavMovieID | PersonID | Movie             |
+------------+----------+-------------------+
|          1 |        1 | American Pie 1    |
|          2 |        1 | American Pie 2    |
|          3 |        1 | American Pie 3    |
|          4 |        3 | A Game of Thrones |
|          5 |        3 | Eragon            |
+------------+----------+-------------------+

现在我只是使用以下查询加入表格:

Select * FROM persons
LEFT JOIN person_fav_artists USING (PersonID)
LEFT JOIN person_fav_movies USING (PersonID);

返回以下结果:

+----------+------+------+----------------+----------------+------------+-------------------+
| PersonID | Name | Age  | FavInterpretID | Interpret      | FavMovieID | Movie             |
+----------+------+------+----------------+----------------+------------+-------------------+
|        1 | Jeff |   22 |              1 | Linkin Park    |          1 | American Pie 1    |
|        1 | Jeff |   22 |              1 | Linkin Park    |          2 | American Pie 2    |
|        1 | Jeff |   22 |              1 | Linkin Park    |          3 | American Pie 3    |
|        1 | Jeff |   22 |              2 | Muse           |          1 | American Pie 1    |
|        1 | Jeff |   22 |              2 | Muse           |          2 | American Pie 2    |
|        1 | Jeff |   22 |              2 | Muse           |          3 | American Pie 3    |
|        1 | Jeff |   22 |              6 | Fort Minor     |          1 | American Pie 1    |
|        1 | Jeff |   22 |              6 | Fort Minor     |          2 | American Pie 2    |
|        1 | Jeff |   22 |              6 | Fort Minor     |          3 | American Pie 3    |
|        1 | Jeff |   22 |              7 | Jay Z          |          1 | American Pie 1    |
|        1 | Jeff |   22 |              7 | Jay Z          |          2 | American Pie 2    |
|        1 | Jeff |   22 |              7 | Jay Z          |          3 | American Pie 3    |
|        2 | Lisa |   15 |              3 | Madonna        |       NULL | NULL              |
|        2 | Lisa |   15 |              4 | Katy Perry     |       NULL | NULL              |
|        2 | Lisa |   15 |              5 | Britney Spears |       NULL | NULL              |
|        3 | Jon  |   30 |           NULL | NULL           |          4 | A Game of Thrones |
|        3 | Jon  |   30 |           NULL | NULL           |          5 | Eragon            |
+----------+------+------+----------------+----------------+------------+-------------------+
17 rows in set (0.00 sec)

到目前为止一切顺利。 我现在的问题是,如果对于'杰夫'这个人'返回'12'行是“正常的”,尽管他只有四个'艺术家'和三个'电影'分配给他。 我想我可能理解为什么结果是这样的,但我认为返回如此多的Rows以获得如此少的实际数据是非常愚蠢的。

我的查询是否有问题或是故意这种行为?

我希望得到的结果如下(仅适用于Jeff):

+----------+------+------+----------------+----------------+------------+-------------------+
| PersonID | Name | Age  | FavInterpretID | Interpret      | FavMovieID | Movie             |
+----------+------+------+----------------+----------------+------------+-------------------+
|        1 | Jeff |   22 |              1 | Linkin Park    |          1 | American Pie 1    |
|        1 | Jeff |   22 |              2 | Muse           |          2 | American Pie 2    |
|        1 | Jeff |   22 |              3 | Fort Minor     |          3 | American Pie 3    |
|        1 | Jeff |   22 |              4 | Jay Z          |          1 | NULL              | <- 'American Pie 1/2/3' would be OK as well.
+----------+------+------+----------------+----------------+------------+-------------------+

感谢您的帮助!

5 个答案:

答案 0 :(得分:1)

查询或结果没有错,它只是返回所有可能的组合。如果数据量很大,一种选择是分成两个单独的查询。

答案 1 :(得分:0)

此行为是故意的。

  1. 你的第一张桌子有一列为杰夫。
  2. 第二个表有4列Jeff,所以连接表给出了 1×4。
  3. 第三个表有3列Jeff,所以连接表给出了 1x4x3。
  4. 你现在有了所有可能的组合。

答案 2 :(得分:0)

我认为这是正常的,因为它正在拍摄所有电影和收藏艺术家的组合。我认为这就是加入的方式。

答案 3 :(得分:0)

您正在使用12条记录获得正确的结果,因为这是您要求数据的正确元组。我不确定你为什么要加入这三个表,因为这两个相关的表并不是同一类型的数据。我建议你选择人和人。电影,然后你可以联合人和&amp;艺术家,因为你的工会会希望列相同,我建议添加一个类型来区分艺术家和电影,然后好名字应该只是一个字符串_值

答案 4 :(得分:0)

尝试将INFT JOIN替换为LEFT JOIN:

     SELECT * 
     FROM persons 
     INNER JOIN person_fav_artists USING (PersonID) 
     INNER JOIN person_fav_movies USING (PersonID);