首页 > 试题广场 >

获取每个部门中薪水最高的员工相关信息

[编程题]获取每个部门中薪水最高的员工相关信息
  • 热度指数:1047364 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
有一个员工表dept_emp简况如下:
emp_no
dept_no
from_date
to_date
10001 d001
1986-06-26 9999-01-01
10002 d001
1996-08-03 9999-01-01
10003 d002
1996-08-03 9999-01-01

有一个薪水表salaries简况如下:
emp_no
salary
from_date
to_date
10001
88958 2002-06-22
9999-01-01
10002
72527 2001-08-02
9999-01-01
10003
92527 2001-08-02 9999-01-01

获取每个部门中薪水最高的员工相关信息给出dept_no, emp_no以及其对应的salary,按照部门编号dept_no升序排列,以上例子输出如下:
dept_no
emp_no
salary
d001 10001
88958
d002 10003
92527
示例1

输入

drop table if exists  `dept_emp` ; 
drop table if exists  `salaries` ; 
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01');
INSERT INTO dept_emp VALUES(10003,'d002','1996-08-03','9999-01-01');

INSERT INTO salaries VALUES(10001,88958,'2002-06-22','9999-01-01');
INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10003,92527,'2001-08-02','9999-01-01');

输出

dept_no|emp_no|salary
d001|10001|88958
d002|10003|92527
正确的运行代码,到底是什么?
为什么尝试验证其他人的代码,都是错误的
发表于 2025-11-03 11:09:17 回复(0)
select r.dept_no,s.emp_no,r.salary
from(
    select d.dept_no, max(s.salary) salary
    from dept_emp d
    inner join salaries s on d.emp_no = s.emp_no
    group by dept_no
    order by dept_no
) r
inner join salaries s on s.salary=r.salary;

发表于 2025-09-29 11:18:58 回复(0)
方法一:先定标准,再找符合标准的人
SELECT
    de.dept_no,
    sa.emp_no,
    sa.salary
FROM
    salaries AS sa
    INNER JOIN dept_emp AS de ON de.emp_no = sa.emp_no
WHERE
    (de.dept_no, sa.salary) IN 
    (SELECT
        dept_no,
        MAX(salary)
    FROM
        salaries
    INNER JOIN dept_emp ON dept_emp.emp_no = salaries.emp_no
    GROUP BY dept_no)
ORDER BY
    de.dept_no ASC;
  1. 子查询部分
    通过 GROUP BY dept_no 分组,计算每个部门的最高薪资,得到 “部门号+该部门最高薪资”的组合。
  2. 主查询部分
    连接 salaries 和 dept_emp 表后,用 WHERE (de.dept_no, sa.salary) IN (...) 筛选出 “部门号和薪资同时匹配子查询结果” 的记录,从而精准定位到每个部门中拿最高工资的员工

第一步:明确目标 —— 我们要什么结果?

我们需要的是 “每个部门里薪资最高的员工”,比如:
  • d001 部门薪资最高的员工是谁?薪资多少?
  • d002 部门薪资最高的员工是谁?薪资多少?
    ……

第二步:先解决 “每个部门的最高薪资是多少”

要找到 “拿最高薪资的员工”,得先知道 “这个部门的最高薪资到底是多少”。
这就像:要找 “班里最高分的同学”,得先算出 “全班最高分是多少”。
怎么算每个部门的最高薪资?
子查询 + 分组
SELECT 
  dept_no,  -- 部门号
  MAX(salary)  -- 每个部门的最高薪资(MAX是求最大值的函数)
FROM 
  salaries  -- 薪资表(存员工薪资)
INNER JOIN dept_emp ON dept_emp.emp_no = salaries.emp_no  -- 关联部门员工表(属于哪个部门)
GROUP BY dept_no  -- 按部门号分组(每个部门单独算最高薪资)
这个子查询会得到类似这样的结果:
dept_no MAX(salary)
d001 88958
d002 43311
d003 94692

第三步:根据 “最高薪资” 找到对应的员工
知道了每个部门的最高薪资,接下来就要找 “哪个员工拿了这个薪资”。
主查询 + 匹配条件
主查询先关联薪资表(salaries)和部门员工表(dept_emp),获取所有员工的 “部门号、员工号、薪资”。
然后通过WHERE (de.dept_no, sa.salary) IN (...)这个条件,筛选出 “部门号和薪资” 匹配子查询结果的员工。
即:
“只保留那些‘部门号是 d001 且薪资是 88958’‘部门号是 d002 且薪资是 43311’…… 的员工”。

第四步:整理结果 —— 按部门号排序

最后用ORDER BY de.dept_no ASC让结果按部门号从小到大排列,看起来更整齐。

方法二:给每个部门的员工排薪资名次,然后只取薪资最高的
SELECT
    dept_no,
    emp_no,
    salary
FROM
    (SELECT
        de.dept_no,
        sa.emp_no,
        sa.salary,
        ROW_NUMBER() OVER (
            PARTITION BY
            de.dept_no
            ORDER BY
                sa.salary DESC,
                sa.emp_no ASC) AS rn
    FROM
        salaries AS sa
    INNER JOIN dept_emp AS de ON de.emp_no = sa.emp_no
    ) AS ranked_data
WHERE
    rn = 1
ORDER BY
    dept_no ASC;
  1. 窗口函数 ROW_NUMBER()
    • PARTITION BY de.dept_no:将数据按部门分组(分区),确保每个部门独立计算排名。
    • ORDER BY sa.salary DESC, sa.emp_no ASC:在每个部门内,先按薪资从高到低排序;若薪资相同,按员工编号(emp_no)从小到大排序,保证排名唯一(避免随机取一条)。
    • 生成的 rank 字段表示每条记录在其部门内的排名(rank=1 即为该部门薪资最高的员工)。
  2. 外层筛选
    通过 WHERE rank = 1 只保留每个部门排名第一的记录,严格实现 “每个部门仅显示一个最高薪资员工” 。
一步:明确目标 —— 每个部门只留薪资最高的员工
比如 d001 部门有 3 个员工,薪资分别是 8000、88958、7000,我们只想要薪资 88958 的那个员工;d002 部门同理,只留该部门薪资最高的人。
二步:给每个部门的员工的薪资排次序
ROW_NUMBER() OVER
 ( PARTITION BY de.dept_no -- 先按“部门”分组(比如d001组、d002组...)
ORDER BY sa.salary DESC, sa.emp_no ASC
 -- 组内按“薪资从高到低”排,薪资相同就按“员工编号从小到大”排 )
AS rank -- 给每条记录贴个序号(rank=1就是组内第一名)
例如,d001部门的员工经过排序后得到如下:
dept_no emp_no salary rank
d001 10001 88958 1
d001 10002 72527 2
d001 10003 65000 3
第三步:只保留 “每个部门的第一名”
子查询将所有员工贴上 “部门内的薪资名次”(rank),接下来只需要在外层查询中筛选出 “rank=1” 的记录:
SELECT dept_no, emp_no, salary
FROM (上面的子查询) AS ranked_data 
WHERE rank = 1 -- 只留每个部门的第一名
第四步:按照部门号升序排列
最后用 ORDER BY dept_no ASC 让结果按部门号(d001、d002、d003...)从小到大排列,方便查看。
发表于 2025-09-23 18:06:16 回复(0)
创建俩虚拟表 employee_info 、dept_max_salary,第一个直接将给的俩表内联起来,第二个获取每个部门的最大薪水
内联俩虚拟表,过滤条件employee_info的salary = dept_max_salary的max_salary,
where a.salary = b.max_salary

     
with
    employee_info as (
        select
            d.emp_no,
            d.dept_no,
            s.salary
        from dept_emp d
        join salaries s
            using(emp_no)
        WHERE
            d.to_date = '9999-01-01'
            AND s.to_date = '9999-01-01'
    ),
    dept_max_salary as (
        select
            dept_no,
            max(salary) as max_salary
        from employee_info
        group by dept_no
    )
SELECT
    a.dept_no,
    a.emp_no,
    b.max_salary as salary
FROM
    employee_info a
join dept_max_salary b
    using(dept_no)
where a.salary = b.max_salary
order by dept_no
with
    employee_info as (
        select
            d.emp_no,
            d.dept_no,
            s.salary
        from dept_emp d
        join salaries s
            using(emp_no)
        WHERE
            d.to_date = '9999-01-01'
            AND s.to_date = '9999-01-01'
    ),
    dept_max_salary as (
        select
            dept_no,
            max(salary) as max_salary
        from employee_info
        group by dept_no
    )
SELECT
    a.dept_no,
    a.emp_no,
    b.max_salary as salary
FROM
    employee_info a
join dept_max_salary b
    using(dept_no)
where a.salary = b.max_salary
order by dept_no
发表于 2025-09-19 14:33:04 回复(0)
连接两表后利用窗口函数ROW_NUMBER()给每个部门内的员工按工资降序排名,然后取第一名即可
注意这里要给派生表随便起给表名

select dept_no, emp_no, salary
from (
    select d.dept_no, s.emp_no, s.salary,
           row_number() over (partition by d.dept_no order by s.salary desc) as rn
    from dept_emp d
    join salaries s on d.emp_no = s.emp_no
) t
where rn = 1
order by dept_no;



发表于 2025-09-18 14:59:32 回复(0)
WITH RankedSalaries AS (
    SELECT
        a.dept_no,
        a.emp_no,
        b.salary,
        ROW_NUMBER() OVER (PARTITION BY a.dept_no ORDER BY b.salary DESC) AS rn
    FROM
        dept_emp a
    JOIN salaries b ON a.emp_no = b.emp_no
)
SELECT
    dept_no,
    emp_no,
    salary
FROM
    RankedSalaries
WHERE
    rn = 1
ORDER BY
    dept_no;

发表于 2025-08-04 20:07:18 回复(0)
SELECT dept_no, emp_no, salary
FROM (
    SELECT dept.dept_no, dept.emp_no, s.salary,
           RANK() OVER (PARTITION BY dept.dept_no ORDER BY s.salary DESC) AS ranking
    FROM dept_emp AS dept
    LEFT JOIN salaries AS s ON dept.emp_no = s.emp_no
) AS ranked
WHERE ranking = 1
ORDER BY dept_no;

发表于 2025-07-23 23:11:52 回复(0)
select a.dept_no
,a.emp_no
,a.salary
from (
    select d.dept_no
    ,d.emp_no
    ,s.salary
    ,rank()over(partition by dept_no order by salary desc) as posn
    from dept_emp as d join salaries as s on d.emp_no = s.emp_no
    where d.to_date = '9999-01-01'
    and s.to_date = '9999-01-01'
) as a
where a.posn = 1
order by dept_no

我感觉最优方法是直接排序,这样不光第一,第二、第三也都能挑出来,并且逻辑上没有问题。如果排名第一的不止一个人,也可以挑选出所有排名第一的。
发表于 2025-07-22 10:55:12 回复(0)
SELECT
    dept_no,
    salaries.emp_no,
    salary
FROM
    dept_emp
    JOIN salaries ON dept_emp.emp_no = salaries.emp_no
where
    (dept_no, salary) in (
        SELECT
            dept_no,
            MAX(salary)
        FROM
            dept_emp
            JOIN salaries ON dept_emp.emp_no = salaries.emp_no
        GROUP BY
            dept_no
    )
ORDER BY
    dept_no
发表于 2025-07-14 15:08:29 回复(0)
select dept_no,emp_no,salary
from(
    select dept_no,dept_emp.emp_no emp_no,salary,
    rank()over(partition by dept_no order by salary desc) posn
    from dept_emp left join salaries on dept_emp.emp_no=salaries.emp_no
) rk
where rk.posn=1
order by dept_no
发表于 2025-07-12 10:07:10 回复(0)
select
    dept_no,
    emp_no,
    salary
from(
    select
        d.dept_no,
        d.emp_no,
        s.salary,
        dense_rank() over (
        partition by dept_no
        order by salary desc) as rk
    from dept_emp d
join salaries s
on d.emp_no = s.emp_no
) as a
where rk = 1
order by dept_no;
发表于 2025-06-24 13:54:47 回复(0)
select a.dept_no,c.emp_no,c.salary
from
(SELECT d.dept_no, MAX(s.salary) salary FROM salaries AS s INNER JOIN dept_emp As d ON d.emp_no = s.emp_no
WHERE d.to_date = '9999-01-01' AND s.to_date = '9999-01-01'
GROUP BY d.dept_no) a join dept_emp b on a.dept_no=b.dept_no
join salaries c on b.emp_no=c.emp_no
where c.salary =a.salary
and b.to_date = '9999-01-01' AND c.to_date = '9999-01-01'
order by a.dept_no
发表于 2025-06-23 17:32:45 回复(0)
select t.dept_no, t.emp_no, t.salary from (
select d.dept_no, d.emp_no, s.salary,row_number() over (partition by d.dept_no order by salary desc) as rk from dept_emp d join salaries s on d.emp_no = s.emp_no) as t where rk = 1 order by t.dept_no asc
发表于 2025-04-20 18:51:38 回复(0)
select d.dept_no,d.emp_no,s.salary
from dept_emp d join salaries s on d.emp_no = s.emp_no
where s.to_date = '9999-01-01'
and(d.dept_no,s.salary) in (
    select d2.dept_no,max(s2.salary)
    from dept_emp d2 join salaries s2 on d2.emp_no = s2.emp_no
    where s2.to_date = '9999-01-01'
    group by d2.dept_no
)
order by d.dept_no
解题思路:
1.主查询部分
SELECT d.dept_no, s.emp_no, s.salary
FROM dept_emp d
JOIN salaries s ON d.emp_no = s.emp_no
从dept_emp和salaries两张表中,连接获取每位员工的部门和当前薪水信息
2.限定只查询当前薪水
WHERE s.to_date = '9999-01-01'
9999-01-01是当前有效薪水的标志,说明这个工资是“现在”的
3.子查询部分(关键)
AND (d.dept_no, s.salary) IN (
  SELECT d2.dept_no, MAX(s2.salary)
  FROM dept_emp d2
  JOIN salaries s2 ON d2.emp_no = s2.emp_no
  WHERE s2.to_date = '9999-01-01'
  GROUP BY d2.dept_no
)
 找出每个部门的“当前最高薪水”,我们再用主查询去找和这个组合相等的(dept_no, salary),就得到了对应的员工
4.排序部分
ORDER BY d.dept_no
让结果按部门编号升序排好


发表于 2025-04-16 22:01:35 回复(0)
SELECT
    o.dept_no,
    e1.emp_no,
    o.salary 
FROM
    dept_emp e1
    INNER JOIN (
    SELECT
        e.dept_no,
        max( s.salary ) salary 
    FROM
        dept_emp e
        INNER JOIN salaries s ON s.emp_no = e.emp_no 
    GROUP BY
        e.dept_no 
    ) o ON e1.dept_no = o.dept_no
    INNER JOIN salaries ss ON ss.emp_no = e1.emp_no 
WHERE
    o.salary = ss.salary 
ORDER BY
    o.dept_no
发表于 2025-04-13 02:30:07 回复(0)
-- 窗口函数
select dept_no,emp_no, salary
from(
select a.dept_no,a.emp_no, b.salary,
dense_rank()over(partition by a.dept_no order by b.salary desc) as rk
from dept_emp a
left join salaries b
on a.emp_no=b.emp_no
where a.to_date='9999-01-01'and b.to_date='9999-01-01'
) t
where rk =1
order by dept_no
发表于 2025-04-09 14:29:00 回复(0)