首页 > 试题广场 >

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

[编程题]获取每个部门中薪水最高的员工相关信息
  • 热度指数:992920 时间限制: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
maxSalary
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
此题思路如下:
1、先用INNER JOIN连接两张表,限制条件是两张表的emp_no相同,即d.emp_no = s.emp_no;
2、选取每个员工当前的工资水平,用d.to_date = '9999-01-01' AND s.to_date = '9999-01-01'作条件限制,因为此表中每条最新记录的 to_date 都用 9999-01-01 表示;
3、用GROUP BY d.dept_no将每个部门分为一组,用MAX()函数选取每组中工资最高者;
4、将salaries用s代替,dept_emp用d代替,最后将MAX(s.salary)用salary代替后输出。
SELECT d.dept_no, s.emp_no, MAX(s.salary) AS 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
------------------------------------------分割线:若存在多条最大记录----------------------------------------
有同学提出疑问,如果存在多条最大记录怎么办?而 MAX 函数根据不同数据库只选择最前一条或最后一条最大记录,其余记录均被忽略。此时解法如下:
1、创建两张表,一张为maxsalary,用于存放当前每个部门薪水的最大值;另一张为currentsalary,用于存放当前每个部门所有员工的编号和薪水;
2、限定条件为两张表的 dept_no 和 salary 相等,这样就可以找出当前每个部门所有薪水等于最大值的员工的相关信息了;
3、最后记得根据 currentsalary.dept_no 升序排列,输出与参考答案相同的记录表。
4、以下代码虽然很长,仔细一看都是基于上面的基础解法变化而来的,中心思想就是绕开 MAX 的特性限制,运用比较的方法选出多个相同的最大值。
SELECT currentsalary.dept_no, currentsalary.emp_no, currentsalary.salary AS salary
FROM 
//创建maxsalary表用于存放当前每个部门薪水的最大值
(SELECT d.dept_no, MAX(s.salary) AS 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) AS maxsalary, 
//创建currentsalary表用于存放当前每个部门所有员工的编号和薪水
(SELECT d.dept_no, s.emp_no, s.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'
) AS currentsalary
//限定条件为两表的dept_no和salary均相等
WHERE currentsalary.dept_no = maxsalary.dept_no
AND currentsalary.salary = maxsalary.salary
//最后以currentsalary.dept_no排序输出符合要求的记录表
ORDER BY currentsalary.dept_no
编辑于 2017-09-13 16:29:27 回复(83)

有的高票的都是错的,MAX(SALARY) 和 emp_no 不一定对应哦!!!

GROUP BY 默认取非聚合的第一条记录!!!!!!

编辑于 2020-11-07 15:04:45 回复(36)
       翻了前几条回复最多的解法,没看到我认为完美的0漏洞解法。编辑器可能很多写法都能通过,但是通过不代表没问题。
       此题常见漏洞:1.emp_no直接和group by dept_no一起使用,拿到了最大salary但是存在emp_no取值其实与salary不匹配的问题;2. 先使用group by获得最高salary,再去用最高salary匹配两表返回dept_no,emp_no信息,这存在A部门的最高薪水,等于B部门非最高薪水时,B部门的非最高薪水也会被显示出来。在此我将我的答案提供出来,自认为不存在以上两点漏洞:
        解法一:(如果同部门有多条同等最大salary,一起显示出来)
select r.dept_no,ss.emp_no,r.maxSalary from (
select d.dept_no,max(s.salary)as maxSalary from dept_emp d,salaries s
where d.emp_no=s.emp_no
and d.to_date='9999-01-01' 
and s.to_date='9999-01-01'
group by d.dept_no
)as r,salaries ss,dept_emp dd
where r.maxSalary=ss.salary
and r.dept_no=dd.dept_no
and dd.emp_no=ss.emp_no
and ss.to_date='9999-01-01'
and dd.to_date='9999-01-01'
order by r.dept_no asc
         解法二:(如果同部门有多条同等最大salary,仅显示一条
select r.dept_no,r.emp_no,max(r.salary) from (
select d.dept_no,d.emp_no,s.salary from dept_emp d,salaries s
where d.emp_no=s.emp_no
and d.to_date='9999-01-01' 
and s.to_date='9999-01-01'
order by s.salary desc
)as r
group by r.dept_no
order by r.dept_no asc
注明两点:
1.题目忘记写一条信息,按照部门编号排序
2.解法二利用了GROUP BY 默认取非聚合数据的第一条记录,所以先排好序,拿到的emp_no第一条信息,也是与最大salary匹配的
3.解法一中使用多表取值,where筛选条件和内连接,on筛选条件,效果一致,可以替换。效率根据不同表的结构,数据结构而定。


发表于 2019-09-12 18:18:04 回复(46)
目前的一些“正确答案”其实不对,因为emp_no是随机返回的,而不是与最大工资相对应的那个

知识点
使用group by子句时,select子句中只能有聚合键、聚合函数、常数。
emp_no并不符合这个要求。

楼上wasrehpic与Linkkuma的答案都可以返回正确值,此处再提供一个参考答案

select de.dept_no, de.emp_no, s.salary

from dept_emp de inner join salaries s

on de.emp_no = s.emp_no

and de.to_date = '9999-01-01'

and s.to_date = '9999-01-01'

where s.salary = (select max(s2.salary)

              from dept_emp de2 inner join salaries s2

              on de2.emp_no = s2.emp_no

              and de2.to_date = '9999-01-01'

              and s2.to_date = '9999-01-01'

              where de2.dept_no = de.dept_no

              group by de2.dept_no)

order by de.dept_no

最后一行的order by子句一定不能少,因为原题目可能漏了一个条件,“按照部门升序排列”
(真是万万没想到。。。)

发表于 2018-08-04 13:18:37 回复(68)
评论区的答案看着看着就看不下去了。写一个我自己觉得很好理解的吧。
我们都知道,gruop by 之后直接查询emp_no默认取非聚合的第一条,不符合我们的目的。还在评论区看到使用窗口函数max(salary) over (partition by dept_no) 也并不能对应部门,样例中d004部门的10003的薪水和d002部门最多薪水43311相等,于是取了10003。但是d004部门最多薪水的员工是10004,也不符合我们的目的。
现在的问题是,我们可以求得每个部门的最大薪水,怎么和员工对应,使得找到对应部门对应薪水的员工号
于是用联合条件
(dept_no,salary) in (select dept_no,max(salary) ……)
完整代码如下:
select dept_no,s.emp_no,salary maxSalary
from dept_emp de join salaries s on de.emp_no=s.emp_no 
where (dept_no,salary) in (select dept_no,max(salary) 
                              from dept_emp de join salaries s 
               on de.emp_no=s.emp_no 
               where s.to_date='9999-01-01' and de.to_date='9999-01-01' 
               group by dept_no)
order by dept_no

编辑于 2022-02-24 17:54:01 回复(26)
本题是一道审核有问题的题目,分为2种情况(用的提交错误时提供的数据):
第一种方案:
SELECT B.dept_no,B.emp_no,A.salary AS salary FROM `salaries` AS A join dept_emp AS B on A.emp_no=B.emp_no
where A.to_date='9999-01-01' and B.to_date='9999-01-01'
GROUP BY B.dept_no
having A.salary=max(A.salary);
说明:用这种方案,先分组,你会发现它分组后默认都是取的第一条数据:

然后我后一句having A.salary=max(A.salary);就会把10003给干掉了,就是查不出来了:
原因是10003与10004同属部门d004,而10004的薪水高于10003,所以max(A.salary)不等于A.salary,导致没有了这条记录。这是此方案存在的问题,把应该显示的10004号员工,对应d004部门的记录给弄丢了,但此方案竟然神奇的通过了。
第二种方案:
SELECT B.dept_no,A.emp_no,MAX(A.salary) AS salary FROM `salaries` AS A join dept_emp AS B on A.emp_no=B.emp_no
where A.to_date='9999-01-01' and B.to_date='9999-01-01'
GROUP BY B.dept_no;
它的结果是:
我们注意d004部门那条记录,是10003号员工对应薪水74057,看表我们知道,10003号员工对应的薪水是43311,10004号员工对应的薪水是74057,这里的结果错位了,错误的原因是因为我用了select MAX(A.salary),查出来的薪水确实的每组最高的,但是它emp_no却默认取了分组后的第一条记录的emp_no。这个方案居然也通过了,我真是纳闷了,大家都没发现吗????如果我说错了的话希望有大神指教,欢迎讨论啊~不要沉!!!!
找了个好办法,却有问题
SELECT dept_no,emp_no,salary from(
SELECT     D.dept_no AS dept_no,S.emp_no AS emp_no,S.salary AS salary from salaries AS S JOIN dept_emp as D on S.emp_no=D.emp_no
where D.to_date='9999-01-01' and S.to_date='9999-01-01' 
ORDER BY salary DESC
) as b
GROUP BY dept_no
先进行降序排序,再分组,结果却是

仍然显示的是10003的43311,绝望啊,我尝试了下,如果先去掉分组:

同样是d001部门,分组后10001怎么就在10002前面,而d004部门的10003怎么跑10004前面去了,这个题有毒啊
编辑于 2018-01-04 17:09:59 回复(23)

个人认为这个是最严谨最正确的写法
1.按照emp_no连接两个表
2.注意时间 需要是当前 两边表的date都要是99990101
3.group by部门号dept_no 添加条件工资=最高工资

SELECT e.dept_no, e.emp_no, s.salary
FROM dept_emp AS e INNER JOIN salaries AS s 
ON e.emp_no = s.emp_no
WHERE e.to_date = '9999-01-01' AND s.to_date = '9999-01-01'
GROUP BY e.dept_no 
HAVING s.salary = MAX(s.salary);
编辑于 2019-03-18 10:26:45 回复(22)
1、方法一:使用窗口排序函数
SELECT D.dept_no,D.emp_no,D.salary 
FROM(
    SELECT 
           DENSE_RANK() OVER (PARTITION BY C.dept_no ORDER BY C.salary DESC) AS raking,
           C.dept_no,
           C.emp_no,
           C.salary 
    FROM (
          SELECT
                A.dept_no,
                A.emp_no,
                B.salary
          FROM 
                dept_emp A
                INNER JOIN salaries B ON A.emp_no = B.emp_no
          WHERE 
                A.to_date = '9999-01-01'
                AND B.to_date = '9999-01-01' 
         ) C 
     ) D 
WHERE D.raking = 1
ORDER BY D.dept_no


【注】DENSE_RANK() OVER(PARTITION dept_no ORDER BY salary DESC)可以得出以
部门为单位的员工的工资排名,可以满足并列第1的要求

2、方法二:如果mysql数据库没有排序函数,则可以使用非等值自连接的方法来实现类似DENSE_RANK()
函数的功能,语句比较长,可以不过原理简单的,如下:
SELECT D.dept_no,D.emp_no,D.salary FROM(
    SELECT (
        SELECT COUNT( DISTINCT F.salary ) 
            FROM(
                  SELECT
                    A.dept_no,
                    A.emp_no,
                    B.salary 
                  FROM
                    dept_emp A
                    INNER JOIN salaries B ON A.emp_no = B.emp_no 
                  WHERE
                    A.to_date = '9999-01-01' 
                    AND B.to_date = '9999-01-01' 
                ) AS F 
        WHERE
            F.salary >= C.salary 
            AND F.dept_no = C.dept_no 
        ) AS raking,
           C.dept_no,C.emp_no,C.salary FROM (
            SELECT
                A.dept_no,
                A.emp_no,
                B.salary
            FROM 
                dept_emp A
            INNER JOIN salaries B ON A.emp_no = B.emp_no
            WHERE 
            A.to_date = '9999-01-01'
            AND B.to_date = '9999-01-01' ) C ) D 
WHERE D.raking = 1
ORDER BY D.dept_no

编辑于 2019-07-02 23:46:36 回复(11)
--评论区的一些答案没有把GROUP BY 默认取非聚合的第一条记录考虑进去
--以下是我的答案:

SELECT r1.dept_no, r1.emp_no, r1.salary 
FROM
    --创建r1表用于存放当前每个部门每个员工的薪水
    (
    SELECT d.dept_no, d.emp_no, s1.salary
    FROM dept_emp d, salaries s1
    WHERE d.to_date='9999-01-01' 
        AND s1.to_date='9999-01-01'
        AND d.emp_no = s1.emp_no)r1
JOIN  --创建r2表用于存放当前每个部门薪水的最大值
    (
    SELECT d.dept_no, MAX(s2.salary) as maxsalary
    FROM dept_emp d
    --为了避免GROUP BY默认取非聚合数据的第一条记录,先把salary排好序
    JOIN (SELECT * FROM salaries ORDER BY salary DESC)s2
    ON d.emp_no = s2.emp_no
    WHERE d.to_date='9999-01-01' 
        AND s2.to_date='9999-01-01'
    GROUP BY d.dept_no)r2
ON r1.salary = r2.maxsalary
    AND r1.dept_no = r2.dept_no
ORDER BY r2.dept_no
编辑于 2019-10-01 22:50:22 回复(8)
#主要问题:通过常规的聚合函数获取salary时,无法正确获取对应的员工编号。
#方法1:使用两张表,写的比较冗长,但是更加直观(吧...)。先获取员工当前薪资表,再获取部门最高薪资表。
#然后用薪资作为筛选条件对应以获取正确的员工编号。
# SELECT t2.dept_no, t1.emp_no, t2.max_salary
# FROM
# (
#     SELECT e.emp_no , e.dept_no , s.salary 
#     FROM dept_emp e
#     JOIN salaries s
#     ON e.emp_no=s.emp_no
#     AND e.to_date='9999-01-01'
#     AND s.to_date='9999-01-01'
# ) t1
# JOIN
# (
#     SELECT e.dept_no , MAX(salary) max_salary
#     FROM dept_emp e
#     JOIN salaries s
#     ON e.emp_no=s.emp_no
#     AND e.to_date='9999-01-01'
#     AND s.to_date='9999-01-01'
#     GROUP BY e.dept_no
# ) t2
# ON t1.dept_no=t2.dept_no
# WHERE t1.salary=t2.max_salary
# ORDER BY t2.dept_no

#方法2:使用窗口函数。本质就是根据部门划分窗口,对每个部门的员工和薪资记录增加独立排序。
#因此只要获取每个部门排名第一的记录就可以了
SELECT t.dept_no, t.emp_no, t.salary
FROM
(
    SELECT d.dept_no, d.emp_no, s.salary, 
    RANK() OVER(PARTITION BY d.dept_no ORDER BY s.salary DESC) dept_s_ranking
    FROM dept_emp d
    JOIN salaries s
    ON d.emp_no=s.emp_no
    AND d.to_date='9999-01-01'
    AND s.to_date='9999-01-01'
)t
WHERE t.dept_s_ranking=1;

发表于 2020-11-24 14:51:47 回复(3)
遇事不决,直接开窗
SELECT a.dept_no, a.emp_no, a.salary AS maxSalary
FROM (SELECT d.emp_no, d.dept_no, s.salary,
     DENSE_RANK() OVER (PARTITION BY d.dept_no ORDER BY s.salary DESC) AS rk
     FROM dept_emp AS d INNER JOIN salaries AS s
     ON d.emp_no = s.emp_no AND d.to_date = '9999-01-01'
     AND s.to_date = '9999-01-01'
     )AS a
WHERE a.rk = 1
ORDER BY a.dept_no;


发表于 2021-09-06 17:28:02 回复(1)

解法一 纯 JOIN

select t.dept_no, j.emp_no, t.maxSalary from
(
select d.dept_no as dept_no, max(s.salary) as maxSalary
from dept_emp d join salaries s on s.emp_no = d.emp_no group by d.dept_no
) as t
inner join
(
select d.dept_no as dept_no, s.salary as salary, d.emp_no as emp_no
from dept_emp d join salaries s on s.emp_no = d.emp_no
) as j
on
j.dept_no = t.dept_no and j.salary = t.maxSalary
order by t.dept_no asc;

通过全部用例
运行时间 60ms
占用内存 6904KB

代码长而不难,比较容易理解。

第一个子查询先聚合,group by 聚合键 和 聚合函数 求出每个部门和它的最高薪水,问题在于没有emp_no,接下来我们补充这个字段。

第二个子查询 join 两张表,得到一张宽表,通过dept_no和salary定位到emp_no。

最后按照部门升序。

解法二


select t.dept_no, s.emp_no, t.maxSalary from 
(
select d.dept_no, max(s.salary) as maxSalary from dept_emp d,salaries s
where d.emp_no = s.emp_no group by d.dept_no
) as t, salaries s, dept_emp d
where 
t.maxSalary = s.salary
and t.dept_no = d.dept_no
and d.emp_no = s.emp_no
order by t.dept_no asc

在子查询里面找到 dept_no 和 maxSalary,外部用 where 条件限定,最后按照部门排序。


解法三 利用 MYSQL 8.0 之后的开窗函数


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

通过全部用例 
运行时间 52ms 
占用内存 6776KB

按照部门分区,再按照薪水倒序排序,取第一条就是最大薪资
first_value(salary) over(partition by d.dept_no order by s.salary desc) as maxSalary
结果还不是我们想要的,每一行记录都会与聚合值拼接成一行,需要再次把  salary 等于最大薪资  maxSalary 的筛选出来
where salary = maxSalary

利用 rank() :
select dept_no, emp_no,salary as maxSalary from
(
select d.dept_no as dept_no, d.emp_no as emp_no, s.salary as salary,
rank() over(partition by d.dept_no order by s.salary desc) as ranking
from dept_emp d join salaries s on s.emp_no = d.emp_no 
) as t where t.ranking = 1;








编辑于 2021-05-22 16:01:28 回复(3)
高分答案和很多通过的情况其实不正确,主要是聚合函数求值后对应的问题。请耐心看完下面的:
自己本地数据库模拟了下:

----------
1.(本题通过,但是d004部门的数据丢了)
SELECT
    d.dept_no,
    d.emp_no,
    s.salary
FROM
    dept_emp d,
    salaries s
WHERE
    d.emp_no = s.emp_no
AND d.to_date = '9999-01-01' and s.to_date='9999-01-01'
GROUP BY
    d.dept_no
HAVING
    s.salary = max(s.salary);

2.(本题通过,但是max(s.salary)和d.emp_no不对应,d004的最高工资是10004,而非10003)
SELECT
    d.dept_no,
    d.emp_no,
    max(s.salary)
FROM
    dept_emp d,
    salaries s
WHERE
    d.emp_no = s.emp_no
AND d.to_date = '9999-01-01' and s.to_date ='9999-01-01'
GROUP BY
    d.dept_no;

3.(网友答案)本题通过。对应关系也正确。
SELECT
    re1.dept_no,
    re2.emp_no,
    re1.salary
FROM
    (
        SELECT
            dept_em.dept_no,
            max(em_sa.salary) salary
        FROM
            (
                (
                    SELECT
                        emp_no,
                        salary
                    FROM
                        salaries
                    WHERE
                        to_date = '9999-01-01'
                ) em_sa
                LEFT JOIN (
                    SELECT
                        emp_no,
                        dept_no
                    FROM
                        dept_emp
                    WHERE
                        to_date = '9999-01-01'
                ) dept_em ON em_sa.emp_no = dept_em.emp_no
            )
        GROUP BY
            dept_no
    ) re1
JOIN (
    SELECT
        dept_em.dept_no,
        em_sa.emp_no,
        em_sa.salary salary
    FROM
        (
            (
                SELECT
                    emp_no,
                    salary
                FROM
                    salaries
                WHERE
                    to_date = '9999-01-01'
            ) em_sa
            LEFT JOIN (
                SELECT
                    emp_no,
                    dept_no
                FROM
                    dept_emp
                WHERE
                    to_date = '9999-01-01'
            ) dept_em ON em_sa.emp_no = dept_em.emp_no
        )
) re2 ON re1.dept_no = re2.dept_no
AND re1.salary = re2.salary
ORDER BY
    re1.dept_no;
4.(本题未通过,但在自己数据库上,测试通过。和第3种的输出一致)
select t.dept_no, de.emp_no,t.maxSalary as salary from dept_emp de,salaries sal,
(SELECT
    d.dept_no,
    max(s.salary) as maxSalary
FROM
    dept_emp d,
    salaries s
WHERE
    d.emp_no = s.emp_no
GROUP BY
    d.dept_no) t where de.dept_no = t.dept_no and de.emp_no = sal.emp_no and sal.salary = t.maxSalary AND de.to_date = '9999-01-01' and sal.to_date ='9999-01-01' ORDER BY de.dept_no;




发表于 2018-07-29 13:14:22 回复(8)

这道题目的判题系统有问题, 很多人都回答错误了, 但是通过了判题系统

下面是真`正确答案的写法:
写法一:

select dept_emp.dept_no as dept_no_a, dept_emp.emp_no, max(salaries.salary) as salary
from dept_emp,salaries
where salaries.emp_no=dept_emp.emp_no
group by dept_emp.emp_no,dept_emp.dept_no
having max(salaries.salary) = 
(
    select max(salaries.salary) 
    from dept_emp inner join salaries
    on salaries.emp_no=dept_emp.emp_no 
    where dept_emp.dept_no = dept_no_a
)
order by dept_no_a

写法二:

select distinct dept_no, s.emp_no, salary
from dept_emp as d inner join salaries as s
on s.emp_no = d.emp_no and s.salary = 
(select s2.salary 
 from salaries as s2 inner join dept_emp as d2 
 on s2.emp_no = d2.emp_no 
 where d2.dept_no = d.dept_no
 order by s2.salary desc
 limit 1
)
order by dept_no
;

写法三:
受限于any_value的实现,如果是返回第一个值就没有问题

select ret.dept_no, any_value(ret.emp_no), max(ret.salary) 
from
(select dept_emp.dept_no,dept_emp.emp_no, max(salaries.salary) as salary
from dept_emp,salaries
where salaries.emp_no=dept_emp.emp_no
group by dept_emp.emp_no,dept_emp.dept_no order by salary desc
) as ret group by ret.dept_no
发表于 2018-04-25 16:21:55 回复(6)
select dept_no,emp_no,salary from 
(select d.dept_no,d.emp_no,s.salary,
 rank() over(partition by d.dept_no order by s.salary desc) rn 
 from dept_emp d,salaries s where d.emp_no=s.emp_no 
and d.to_date='9999-01-01'
and s.to_date='9999-01-01')
a where rn=1
发表于 2018-08-09 10:26:39 回复(6)
select X.dept_no,Y.emp_no,Y.salary
from
(select d.dept_no,max(salary) max_salary
from dept_emp d,salaries s
where d.emp_no=s.emp_no and s.to_date='9999-01-01' and d.to_date='9999-01-01'
group by dept_no) as X,
(select d.emp_no,d.dept_no,s.salary
from dept_emp d,salaries s
where d.emp_no=s.emp_no and s.to_date='9999-01-01' and d.to_date='9999-01-01') as Y
where X.dept_no=Y.dept_no and X.max_salary=Y.salary
order by X.dept_no
第一次写就通过了,这是我的思路,我认为十分清晰
发表于 2020-02-25 12:38:14 回复(6)
group by 后面必须有select字段中非聚合函数的字段,所以个人觉得参考答案后应该还有emp_no
发表于 2017-07-17 16:58:25 回复(6)

题目要求获取所有部门中员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary,按照部门编号升序排列。

错误总结:1).groupby子句常见错误
                      SELECT 子句中只能存在以下三种元素。
                      ● 常数  ● 聚合函数  ● GROUP BY子句中指定的列名(也就是聚合键)

#错误用法
SELECT product_name, purchase_price, COUNT(*) -- 列名product_name不能包含
FROM Product GROUP BY purchase_price;
                    2).同一部门存在多个拿最高薪的员工, 怎么办?

个人思路:创建临时表T1,T2。T1获取两表部门编号dept_no以及对应的最高薪maxSalary记录。T2获取两表对应的部门编号dept_no、工资salary和员工编号emp_no记录。T1 join T2 on T1.maxSalary =T2.salary and T1.dept_no=T2.dept_no。T1连接T2条件为相同部门编号下员工的薪资等于最高薪资。

代码:

select T1.dept_no,T2.emp_no,T1.maxSalary
from (
        select de.dept_no,max(salary) as maxSalary
        from dept_emp de join salaries sa
            on de.emp_no=sa.emp_no
        group by dept_no
    )as T1 
    join
    (
        select de.dept_no,sa.salary,sa.emp_no
        from dept_emp de join salaries sa
            on de.emp_no=sa.emp_no
    )as T2
    on T1.maxSalary =T2.salary
        and T1.dept_no=T2.dept_no
order by dept_no


发表于 2021-03-03 11:25:53 回复(1)
这题只需要分两步分析就可以了,😶
😶第一步,先查找出每个部门的最高工资,得到一张有 部门编号最高工资 两列的 ,起别名 tm
(select d.dept_no,max(s.salary) maxsalary from dept_emp d,salaries s where d.emp_no=s.emp_no group by d.dept_no) tm

😶第二步,这可以看作是 三张互相有关联条件的表,(A 关联 B),(A 关联 C),(B 关联 C)
tm.maxsalary=s.salary     
tm.dept_no=d.dept_no
d.emp_no=s.emp_no

😶第三步:套用基础语法select a.*,b,*,c.* from a,b,c where 关联条件;
代码如下:

select d.dept_no,d.emp_no,maxsalary
from
(select d.dept_no,max(s.salary) maxsalary from dept_emp d,salaries s where d.emp_no=s.emp_no group by d.dept_no) tm,
dept_emp d,salaries s 

where tm.maxsalary=s.salary
and tm.dept_no=d.dept_no
and d.emp_no=s.emp_no
order by d.dept_no;
发表于 2022-01-14 00:19:09 回复(1)
不明白评论区为什么搞得这么复杂,mysql8.0开始就有了窗口函数,开窗可以很快就解决。然后如果你要杠我实际中Mysql如果版本没这么高怎么办,我想说实际业务就不会完全由mysql来做,在业务代码里面分两次查数据库就搞定了。既然是为了做题,那就怎么简单怎么来。
而且这种需求多出现在大数据分析,在OLAP的数据库中,用于数据分析的话,是必定支持窗口函数的。再者,要是让我设计生产上的表的话,我也不会像题目这样设计,血缘关系的两个表之间必定会有字段冗余的。
# 开窗函数,分组排序后取每组第一行
SELECT dept_no, emp_no, salary maxSalary
FROM  (SELECT  dept.dept_no, dept.emp_no, sal.salary, 
               DENSE_RANK() over (partition by dept_no order by salary desc) as rownum 
        FROM dept_emp dept LEFT JOIN salaries sal ON dept.emp_no = sal.emp_no) tmp
WHERE rownum = 1
ORDER BY dept_no



发表于 2021-09-18 15:24:08 回复(3)