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

Posted

技术标签:

【中文标题】如何在 MySQL 中的两个表之间进行两次连接,以使它们相互链接?【英文标题】:How to make two joins between two tables in MySQL such that they are interlinked to each other? 【发布时间】:2021-12-08 17:47:26 【问题描述】:

我在公司数据库中有两个名为 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    |       |
+----------------+-------------+------+-----+---------+-------+

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

我会以循环方式(非正式地说)在这两个表之间形成两个连接,这样employee.branch_idbranch.branch_id 形成一个连接,而branch.manager_id 与@ 形成一个连接987654341@.

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

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

P.S:我的问题与上述问题中的this question 不同,两个连接的 LEFT 表是相同的,而在我的情况下,它不是。

【问题讨论】:

不清楚您的假设或确切问题是什么,请提出 1 个清晰准确的完整问题及其示例。根据权威文件证明,人们可能会发现自己的误解。请在代码问题中提供minimal reproducible example。使用足够多的单词、句子和对部分示例的引用来清楚完整地表达你的意思。 PS将与您的问题相关的所有内容放在帖子本身并将其与您的帖子相关联,不要指望我们阅读另一篇帖子并猜测相关的内容或方式。 How to AskHelp center @philipxy 我会以更好的方式编辑和重写问题。对不起,不清楚的问题。 FKs ("relationships") are not needed to query. (And tables represent relation(ship)s/associations.) 约束(包括 FK 和 PK)不需要为了记录或查询而持有、声明或知道。联接是二元的,左表是一系列先前不带括号的联接的结果。除了输出列的顺序,inner & cross join 没有方向,t join u on c 就是 u join t on c。您只需要在点之前提及一个表格/别名。 Re self-join & querying generally. 我认为显示表格的最佳方式是执行SHOW CREATE TABLE table_name; 并将结果发布到您的问题中。它不仅会显示列名。 【参考方案1】:

如何解决问题

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

@philipxy 在对此问题的评论中写道:

约束(包括 FK 和 PK)不需要为了记录或查询而持有、声明或知道。连接是二元的,左表是一系列先前没有括号的连接的结果。除了输出列顺序,inner & cross join 没有方向,t join u on c 就是 u join t on c。

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

问题的解决办法

您可以编写一个 SQL 查询,查询 employee 表中的 first_namelast_namebranch_id 以及 branch 表中的 branch_name,并在两个表之间形成连接基于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           |
+------------+-----------+-----------+-------------+--------+--------------------+-------------------+

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

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

学分

@philpxy 的 cmets 关于这个问题

【讨论】:

以上是关于如何在 MySQL 中的两个表之间进行两次连接,以使它们相互链接?的主要内容,如果未能解决你的问题,请参考以下文章

mysql中两个大表之间的连接查询

MySQL8:连接查询

在两个不同数据库中的表之间连接?

比较与特定字段有关的两个表之间的差异时如何正确连接

Mysql:视图与循环表连接

在时间戳略有不同的2个不同数据库中的表之间连接(MySQL)