MySQL - 将表连接到自身/子查询

MySQL - joining a table to itself / sub queries

提问人:David H 提问时间:3/11/2022 最后编辑:David H 更新时间:3/11/2022 访问量:73

问:

我正在就我最近弄错的评估问题寻求帮助,我已经尝试了许多解决方案,并认为我有点知道我想做什么,但似乎无法弄清楚语法。

我有一个表格,如下所示,但有更多记录。

MyTable
ID   Name            DivisionID   ManagerID   Salary
123  John Smith      100          789         40000
456  Harold Johnson  101          null        60000
789  Vicky Brown     100          null        80000

并且必须选择薪水第三高的人的那一行,我没有问题。但是,我还需要返回 Manager Name,而不是 ManagerID,这需要从同一表中查找。

我尝试了以下解决方案,这似乎有点不优雅,并且必须在其中硬编码相同的查询,因此不适合扩展或一般用途:

SELECT 
table.ID, 
Name,
DivisionID,
(SELECT 
    Name FROM table WHERE id=(
        SELECT ManagerID FROM table ORDER BY Salary DESC LIMIT 2,1)
) AS ManagerName,
Salary

FROM table
ORDER BY Salary DESC LIMIT 2,1;

我认为可能有一些方法可以对子查询做到这一点,例如首先在仅经理 ID 和名称的查询中选择一个单独的表,然后从中进行选择 - 但我似乎无法正确理解语法或了解它。我认为表别名也可能是可能的,我从同一表中以不同的别名选择两个不同的结果,然后将两者连接起来,但再次无法弄清楚如何做到这一点。以下是我尝试对别名执行的操作

SELECT 
a.ID, 
a.Name,
a.DivisionID,
b.Name AS ManagerName
a.Salary

FROM table a
INNER JOIN table b ON a.ManagerID=b.ID
ORDER BY Salary DESC LIMIT 2,1;
MySQL SQL 联接 嵌套 子查询

评论


答:

2赞 Thorsten Kettner 3/11/2022 #1

首先,当被要求返回第 n 个最大/最小值时,您必须问在出现平局时该怎么办。他们想要薪水第三高的人,所以薪水是 1000、1000、900、900、800、800、700、600、500,我想你想归还收入 800 的人,因为这是第三高的薪水。如果你只是按工资排序,跳过两个,拿第三个,那么你随意挑选一个工资为900的人,900甚至不是第三高的,而是第二高的工资。

为了获得经理,只需再次加入表格即可。对于薪水第三高的员工本身就是经理的情况,您应该使用外部联接。

直接的解决方案是用以下命令对行进行排名:DENSE_RANK

select *
from
(
  select t.*, dense_rank() over (order by salary desc) as rnk
  from mytable t
) employee
left join mytable manager on manager.id = employee.managerid
where employee.rnk = 3;

MySQL从版本8开始支持。在旧版本中,您必须再次查找同一表。选择不同的工资,并在这些销售中使用您的限制/抵消条款。DENSE_RANK

select *
from mytable employee
left join mytable manager on manager.id = employee.managerid
where employee.salary =
(
  select distinct salary
  from mytable
  order by salary desc
  limit 2, 1
);

演示:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=6b17e369fcd4f99ddc6c268de15f08a1

评论

0赞 David H 3/11/2022
哦,好的,谢谢,这很有帮助 - 你知道我如何从同一张表中添加经理姓名吗?我只是做了一些编辑以使其更清晰,并且想知道替换图像的表格来自哪里 - 我想那一定是您的编辑,谢谢。
1赞 Thorsten Kettner 3/11/2022
哦,对不起,我错过了那个经理的事情。这确实是另一种自我加入。我一会儿会更新我的答案。
1赞 SOS 3/11/2022
^^ 关于“领带”和外部连接的优点(...同上,这是一个好问题!
1赞 nbk 3/11/2022 #2

Maka a subquersy form you code for the thrd and join selj join the table

这也适用于 MySQL 5.7 及更早版本

CREATE TABLE MyTable (
  `ID` INTEGER,
  `Name` VARCHAR(14),
  `DivisionID` INTEGER,
  `ManagerID` VARCHAR(4),
  `Salary` INTEGER
);

INSERT INTO MyTable
  (`ID`, `Name`, `DivisionID`, `ManagerID`, `Salary`)
VALUES
  ('123', 'John Smith', '100', '789', '40000'),
  ('456', 'Harold Johnson', '101', 'null', '60000'),
  ('789', 'Vicky Brown', '100', 'null', '80000');
SELECT m1.ID, m1.Name, m1. DivisionID,m2. Name, m1.Salary 
FROM (SELECT `ID`, `Name`, `DivisionID`, `ManagerID`, `Salary` FROM MyTable ORDER BY Salary DESC LIMIT 2,1) m1 JOIN MyTable m2 on m1.ManagerID = m2.ID
 ID | Name       | DivisionID | Name        | Salary
--: | :--------- | ---------: | :---------- | -----:
123 | John Smith |        100 | Vicky Brown |  40000

db<>fiddle 在这里