繁体   English   中英

如何在 MySQL 中的两个表之间进行两个连接,使它们相互关联?

[英]How to make two joins between two tables in MySQL such that they are interlinked to each other?

我在名为employeebranch的公司数据库中有两个表,每个表都有一个外键。 employee表如下所示:

+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| emp_id     | int         | NO   | PRI | NULL    | auto_increment |
| first_name | varchar(30) | YES  |     | NULL    |                |
| last_name  | varchar(30) | YES  |     | NULL    |                |
| birth_date | date        | YES  |     | NULL    |                |
| sex        | varchar(1)  | YES  |     | NULL    |                |
| salary     | int         | YES  |     | NULL    |                |
| super_id   | int         | YES  | MUL | NULL    |                |
| branch_id  | int         | YES  | MUL | NULL    |                |
+------------+-------------+------+-----+---------+----------------+

分支表如下所示:

+----------------+-------------+------+-----+---------+-------+
| Field          | Type        | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| branch_id      | int         | NO   | PRI | NULL    |       |
| branch_name    | varchar(30) | YES  |     | NULL    |       |
| mgr_id         | int         | YES  | MUL | NULL    |       |
| mgr_start_date | date        | YES  |     | NULL    |       |
+----------------+-------------+------+-----+---------+-------+

在employee表中, branch_id外键引用了branch表的branch_id 在分支表中, manager_id外键引用employee_id中的employee表。

我会以循环方式(非正式地说)在这两个表之间形成两个连接,这样employee.branch_idbranch.branch_id形成连接,并且branch.manager_idemployee.employee_id形成连接。

所以我希望这两个连接的查询返回的是:

employee.first_name AS employee_name, employee.branch_id, branch.branch_name, branch.manager_id, employee.employee_id AS manager_name

我想不出这个问题的可能解决方案,因为每个连接中的 LEFT 表是不同的,而且我不知道如何在单个 SQL 查询中为每个连接定义多个 LEFT 表。

数据库管理系统:MySQL v8.0.26

PS:我的问题与上述问题中的这个问题不同,两个连接的 LEFT 表是相同的,而在我的情况下,它不是。

如何着手解决问题

通过使用表别名,可以在两列之间形成两个连接。 如题所述,在employeebranch表之间要形成一个join,在branchemployee表之间需要形成另一个join。 这些类型的连接有点棘手的部分是在连接两个表的ON关键字之后指定的关系。

正如@philipxy 在对这个问题的评论中所写:

约束(包括 FK 和 PK)不需要为了记录或查询而保持、声明或知道。 联接是二进制的,左表是没有括号的系列中任何先前联接的结果。 除了输出列顺序,内联和交叉联结没有方向,t join u on c 是 u join t on c。

因此,根据评论,我们将在employeebranch之间形成一个连接,并在employee和名为branch2的分支表的别名之间形成另一个连接。 这里常见的困惑是大多数人(包括我之前)认为连接有一个“方向”,philipxy 在他的上述评论中涵盖了这一点。

问题的解决方案

你可以写一个SQL查询,其查询first_namelast_namebranch_idemployee表和branch_namebranch表和形成的基础上,这两个表之间的联接branch_id 您必须从名为branch2的分支表的别名中查询mgr_id 您必须从员工表中查询分公司经理的first_namelast_name 您可以根据emp_id轻松加入员工和分支表,这样mgr_id = emp_id

您最终可以为该问题编写 SQL 查询,如下所示:

SELECT employee.first_name, employee.last_name, employee.branch_id,
branch.branch_name,
branch2.mgr_id, employee.first_name AS manager_first_name, employee.last_name AS manager_last_name
FROM employee
JOIN branch ON employee.branch_id=branch.branch_id
JOIN branch branch2 ON branch2.mgr_id=employee.emp_id;

额外的信息

上面提到的查询将返回:

+------------+-----------+-----------+-------------+--------+--------------------+-------------------+
| first_name | last_name | branch_id | branch_name | mgr_id | manager_first_name | manager_last_name |
+------------+-----------+-----------+-------------+--------+--------------------+-------------------+
| David      | Wallace   |         1 | Corporate   |    100 | David              | Wallace           |
| Michael    | Scott     |         2 | Scranton    |    102 | Michael            | Scott             |
| Josh       | Porter    |         3 | Stamford    |    106 | Josh               | Porter            |
+------------+-----------+-----------+-------------+--------+--------------------+-------------------+

这些结果可能看起来毫无用处,因为我们在表之间形成了INNER JOIN ,因此它只返回作为特定分支“经理”的员工的姓名。 如果您在表之间形成LEFT JOIN而不是INNER JOIN您将获得如下结果:

+------------+-----------+-----------+-------------+--------+--------------------+-------------------+
| first_name | last_name | branch_id | branch_name | mgr_id | manager_first_name | manager_last_name |
+------------+-----------+-----------+-------------+--------+--------------------+-------------------+
| David      | Wallace   |         1 | Corporate   |    100 | David              | Wallace           |
| Jan        | Levinson  |         1 | Corporate   |   NULL | Jan                | Levinson          |
| Michael    | Scott     |         2 | Scranton    |    102 | Michael            | Scott             |
| Angela     | Martin    |         2 | Scranton    |   NULL | Angela             | Martin            |
| Kelly      | Kapoor    |         2 | Scranton    |   NULL | Kelly              | Kapoor            |
| Stanley    | Hudson    |         2 | Scranton    |   NULL | Stanley            | Hudson            |
| Josh       | Porter    |         3 | Stamford    |    106 | Josh               | Porter            |
| Andy       | Bernard   |         3 | Stamford    |   NULL | Andy               | Bernard           |
| Jim        | Halpert   |         3 | Stamford    |   NULL | Jim                | Halpert           |
+------------+-----------+-----------+-------------+--------+--------------------+-------------------+

这些结果并不像预期的那样,因为不是任何分支机构经理的员工只有一个带有NULL值的mgr_id ,而他们mgr_id的分支机构实际上有一个经理。 由于mgr_id为 NULL, manager_first_namemanager_last_name也有意想不到的结果。

发生上述情况是因为我们不能为两个员工使用相同的经理,因为mgr_id不能mgr_id相同,因为它是emp_id ,它是employee表的主键。

学分

  • @philpxy 对这个问题的评论

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM