简体   繁体   English

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

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

I have two tables in a company database named employee and branch with a single foreign key each.我在名为employeebranch的公司数据库中有两个表,每个表都有一个外键。 The employee table looks like this: 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    |                |
+------------+-------------+------+-----+---------+----------------+

And the branch table looks like this:分支表如下所示:

+----------------+-------------+------+-----+---------+-------+
| 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    |       |
+----------------+-------------+------+-----+---------+-------+

In the employee table, the branch_id foreign key references the branch_id of the branch table.在employee表中, branch_id外键引用了branch表的branch_id In the branch table, the manager_id foreign key references the employee_id of the employee table.在分支表中, manager_id外键引用employee_id中的employee表。

I would form two joins between these two tables in circular fashion (saying informally) such that employee.branch_id forms a join with branch.branch_id , and such that branch.manager_id forms a join with employee.employee_id .我会以循环方式(非正式地说)在这两个表之间形成两个连接,这样employee.branch_idbranch.branch_id形成连接,并且branch.manager_idemployee.employee_id形成连接。

So what I want the query with these two joins to return is:所以我希望这两个连接的查询返回的是:

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

I couldn't think of a possible solution to this issue as the LEFT table in each of the joins is different and I don't know how to define multiple LEFT tables for each join in a single SQL query.我想不出这个问题的可能解决方案,因为每个连接中的 LEFT 表是不同的,而且我不知道如何在单个 SQL 查询中为每个连接定义多个 LEFT 表。

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

PS: My question is different from this question as in the aforementioned question, the LEFT table for both of the joins is the same and in my case, it is not. PS:我的问题与上述问题中的这个问题不同,两个连接的 LEFT 表是相同的,而在我的情况下,它不是。

How to proceed towards the solution如何着手解决问题

Two joins can be formed between two columns by using Table aliases.通过使用表别名,可以在两列之间形成两个连接。 As the question specifies, that one join is to be formed between the employee and the branch table, and another join needs to be formed between the branch and the employee table.如题所述,在employeebranch表之间要形成一个join,在branchemployee表之间需要形成另一个join。 The little bit tricky part of these types of joins is the relation specified after the ON keyword that joins the two tables.这些类型的连接有点棘手的部分是在连接两个表的ON关键字之后指定的关系。

As @philipxy writes in a comment to this question:正如@philipxy 在对这个问题的评论中所写:

Constraints (including FKs & PKs) need not hold, be declared or be known in order to record or query.约束(包括 FK 和 PK)不需要为了记录或查询而保持、声明或知道。 Joins are binary, the left table is the result of any previous joins in a series without parentheses.联接是二进制的,左表是没有括号的系列中任何先前联接的结果。 Except for output column order, inner & cross joins have no direction, t join u on c is u join t on c.除了输出列顺序,内联和交叉联结没有方向,t join u on c 是 u join t on c。

So according to the comment, we would form a join between employee and branch and another join between employee and an alias of branch table called branch2 .因此,根据评论,我们将在employeebranch之间形成一个连接,并在employee和名为branch2的分支表的别名之间形成另一个连接。 The common confusion here is that most people(including me earlier) think that there is a "direction" of joins, the thing that philipxy covers in his aforementioned comment.这里常见的困惑是大多数人(包括我之前)认为连接有一个“方向”,philipxy 在他的上述评论中涵盖了这一点。

The solution to the problem问题的解决方案

You can write a SQL query which queries the first_name , last_name and branch_id from the employee table and the branch_name from the branch table and forms a join between the two tables on the basis of branch_id .你可以写一个SQL查询,其查询first_namelast_namebranch_idemployee表和branch_namebranch表和形成的基础上,这两个表之间的联接branch_id You have to query the mgr_id from the alias of the branch table called branch2 ;您必须从名为branch2的分支表的别名中查询mgr_id you have to query the first_name and the last_name of the branch managers from the employee table.您必须从员工表中查询分公司经理的first_namelast_name You can easily join the employee and the branch table on the basis of emp_id such that the mgr_id = emp_id .您可以根据emp_id轻松加入员工和分支表,这样mgr_id = emp_id

You can finally write the SQL query for the problem like this:您最终可以为该问题编写 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;

Extra information额外的信息

The above mentioned query would return this:上面提到的查询将返回:

+------------+-----------+-----------+-------------+--------+--------------------+-------------------+
| 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            |
+------------+-----------+-----------+-------------+--------+--------------------+-------------------+

These results might look useless as we have formed an INNER JOIN between the tables so it just returns us the name of the employees who are "managers" of a specific branch.这些结果可能看起来毫无用处,因为我们在表之间形成了INNER JOIN ,因此它只返回作为特定分支“经理”的员工的姓名。 If you form a LEFT JOIN between the tables instead of an INNER JOIN you would get results like this:如果您在表之间形成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           |
+------------+-----------+-----------+-------------+--------+--------------------+-------------------+

These results were not as expected as the employees who are not managers of any branch just have a mgr_id with NULL value whereas the branch that they word in actually has a manager.这些结果并不像预期的那样,因为不是任何分支机构经理的员工只有一个带有NULL值的mgr_id ,而他们mgr_id的分支机构实际上有一个经理。 With the mgr_id being NULL, the manager_first_name and manager_last_name have unexpected results too.由于mgr_id为 NULL, manager_first_namemanager_last_name也有意想不到的结果。

The above occurs because we cannot have the same manager for two employees because mgr_id can not be the same accross rows as it is the emp_id which is the PRIMARY KEY of the employee table.发生上述情况是因为我们不能为两个员工使用相同的经理,因为mgr_id不能mgr_id相同,因为它是emp_id ,它是employee表的主键。

Credits学分

  • @philpxy 's comments on this question @philpxy 对这个问题的评论

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

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