Leetcode的SQL题解:185. 部门工资前三高的员工

题目

查询部门工资前三高的员工。

我用的数据库是oracle。
下面是数据表的信息。
Employee表数据:

| ID | NAME | Salary | DepartmentId |
| -- | ---- | ------ | ------------ |
|1 |    Joe     |   85000   |   1   |
|2 |    Henry   |   80000   |   2   |
|3 |    Sam     |   60000   |   2   |
|4 |    Max     |   90000   |   1   |
|5 |    Janet   |   69000   |   1   |
|6 |    Randy   |   85000   |   1   |
|7 |    Will    |   70000   |   1   |
|8 |    edav    |   50000   |   2   |
|9 |    easonv  |   40000   |   2   |

8、9行为我自行添加,为了更清晰展示查询结果。

创建表

Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id 。

create table Employee (
  Id number(5),
  Name varchar2(10) ,
  Salary number(5),
  DepartmentId number(5)
);
 

Department 表包含公司所有部门的信息。

create table Department  (
  Id number(5),
  Name varchar2(10) 
);

插入数据Employee,脚本如下

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('1', 'Joe', '85000', '1');

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('2', 'Henry', '80000', '2');

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('3', 'Sam', '60000', null);

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('4', 'Max', '90000', '1');

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('5', 'Janet', '69000', '1');

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('6', 'Randy', '85000', '1');

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('7', 'Will', '70000', '1');

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('8', 'eda', '50000', '2');

insert into Employee (ID, NAME, SALARY, DEPARTMENTID)
values ('9', 'eason', '40000', '2');

插入数据Department,脚本如下

insert into Department (ID, NAME)
values ('1', 'IT');

insert into Department (ID, NAME)
values ('2', 'Sales');

查询

以下使用四种SQL语句查出的结果,前两个是用oracle特有函数,后两个是标准SQL92写法。

你觉得哪个对?哪个性能高?

函数1 ROW_NUMBER

select Department,Employee,Salary
 from (select (ROW_NUMBER()
               over(PARTITION by t1.departmentid order by Salary desc)) lev,
              t2.name Department,
              t1.name Employee,
              t1.Salary Salary
         from Employee t1, Department t2
        where t1.departmentid = t2.id) A
where lev <= 3;

函数2 dense_rank

select D.Name Department, E.Name Employee, E.Salary Salary
    from (select Name,
                                                        Salary,
                                                        DepartmentId,
                                                        dense_rank() over(partition by DepartmentId order by Salary desc) Trank
                                    from Employee) E
right join Department D
            on E.DepartmentId = D.id
where Trank <= 3;

通用写法1

select d.name as Department, e.name as Employee, e.salary as Salary
  from employee  e
 inner join department  d
    on e.DepartmentId = d.id
 where  (select count(distinct salary)
          from employee
         where salary > e.salary
           and departmentid = e.DepartmentId) < 3
 order by e.departmentid, Salary desc;

通用写法2

SELECT t3.name Department, t2.name Employee, t2.salary Salary
    FROM Employee t2, Department t3
WHERE t2.id NOT IN (SELECT b.id
                        FROM Employee a, Employee b
                        WHERE a.DepartmentId = b.DepartmentId
                                AND a.salary > b.salary
                                GROUP BY b.id
                                HAVING COUNT(*) >= 3)
        AND t2.DepartmentId = t3.id
ORDER BY Department, t2.salary DESC;

吐槽

感兴趣的同学可以自己跑下。

我个人觉得所谓官方答案是有问题的。

官方题解如下,mysql版本:

SELECT d.Name AS 'Department', e1.Name AS 'Employee', e1.Salary
    FROM Employee e1
    JOIN Department d
            ON e1.DepartmentId = d.Id
    WHERE 3 > (SELECT COUNT(DISTINCT e2.Salary)
                FROM Employee e2
                WHERE e2.Salary > e1.Salary
            AND e1.DepartmentId = e2.DepartmentId);

改写成oracle版,加上排序:

SELECT d.Name Department, e1.Name Employee, e1.Salary
    FROM Employee e1
    JOIN Department d
            ON e1.DepartmentId = d.Id
    WHERE 3 > (SELECT COUNT(DISTINCT e2.Salary)
                FROM Employee e2
                WHERE e2.Salary > e1.Salary
            AND e1.DepartmentId = e2.DepartmentId)
     order by d.id,salary desc

查出来的数据是与通用写法1一样的,
两个同样的85000的数据

|序号| Department | Employee | Salary |
|--- | ---- | ------- | ------------ |
|1 |    IT  |   Max   | 90000
|2 |    IT  |   Randy | 85000
|3 |    IT  |   Joe   | 85000
|4 |    IT  |   Will  | 70000
|5 |    Sales | Henry | 80000
|6 |    Sales | Sam   | 60000
|7 |    Sales | eda|    50000

这个题目出的歧义太大,如果是在考试中,应该是查出前三名、前四名的都对。

个人认为应该查出前三名应该是不包含70000这条数据的,就算是并列第二,那么就应该没有第三了,高校排名不也是这样吗?

所以私以为正确答案应该是查出这样的数据

|序号| Department | Employee | Salary |
|--- | ---- | ------- | ------------ |
|1 |    IT  |   Max   | 90000
|2 |    IT  |   Randy | 85000
|3 |    IT  |   Joe   | 85000
|4 |    Sales | Henry | 80000
|5 |    Sales | Sam   | 60000
|6 |    Sales | eda|    50000

那么,我写的四条语句中,应该是函数1及通用写法2可以满足这个条件。


我的公众号
1349401-20190707214822366-1380504658.jpg

发布了63 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yy448671246/article/details/103867540