部门工资最高的员工

Posted

技术标签:

【中文标题】部门工资最高的员工【英文标题】:Employees with largest salary in department 【发布时间】:2013-05-23 20:56:12 【问题描述】:

我今天在 Hacker News 上发现了几个 SQL tasks,但是我一直在解决 Postgres 中的第二个任务,我将在这里描述:

您有以下简单的表结构:

列出各自部门薪水最高的员工。

我设置了一个 SQL Fiddle here 供您使用。它应该返回特里罗宾逊,劳拉怀特。除了他们的名字,还应该有他们的薪水和部门名称。

此外,我很想知道一个查询会返回 Terry Robinsons(销售部门的最高薪水)和 Laura White(营销部门的最高薪水)以及 IT 部门的空行,并带有 @ 987654324@作为员工;明确说明该部门没有员工(因此没有人工资最高)。

【问题讨论】:

看起来微不足道,恕我直言。你试过什么? 你的小提琴是为 mysql 设置的,而问题是关于 Postgres? 【参考方案1】:

返回一个每个部门工资最高的员工。

使用DISTINCT ON 进行更简单、更快速的查询,满足您的所有要求:

SELECT DISTINCT ON (d.id)
       d.id AS department_id, d.name AS department
      ,e.id AS employee_id, e.name AS employee, e.salary
FROM   departments d
LEFT   JOIN employees e ON e.department_id = d.id
ORDER  BY d.id, e.salary DESC;

->SQLfiddle(用于 Postgres)。

另请注意LEFT [OUTER] JOIN,它会在结果中保留没有员工的部门。

这仅选择每个部门的 one 员工。如果有多个共享最高薪水,您可以添加更多 ORDER BY 项目以特别选择一个。否则,会从同行中任意挑选一个。 如果没有员工,仍会列出部门,其中员工列的值为 NULL

您可以简单地在SELECT 列表中添加您需要的任何列。

在此相关答案中找到该技术的详细说明、链接和基准:Select first row in each GROUP BY group?

除此之外:使用非描述性列名(如 nameid)是一种反模式。应该是employee_idemployee等。

返回所有个每个部门薪水最高的员工。

使用窗口函数rank()(类似@Scotch already posted,只是更简单更快):

SELECT d.name AS department, e.employee, e.salary
FROM   departments d
LEFT   JOIN (
   SELECT name AS employee, salary, department_id 
         ,rank() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rnk
   FROM   employees e
   ) e ON e.department_id = d.department_id AND e.rnk = 1;

与您的示例(没有关联)的上述查询结果相同,只是慢了一点。

【讨论】:

【参考方案2】:

这基本上就是你想要的。 Rank() Over

SELECT ename ,
       departments.name
FROM ( SELECT ename ,
              dname
       FROM ( SELECT employees.name as ename ,
                     departments.name as dname , 
                     rank() over (
                       PARTITION BY employees.department_id 
                       ORDER BY employees.salary DESC
                       )
              FROM Employees
              JOIN Departments on employees.department_id = departments.id
            ) t
       WHERE rank = 1
     ) s
RIGHT JOIN departments on s.dname = departments.name

【讨论】:

您可能已将其设置为没有 Rank() over 函数的 MySQL。他说 Postgres。 哦!我的错。你能解释一下 rank() 和分区是如何工作的吗?可能是为什么它比 Rachcha 提出的更有效。 没有问题。乍一看,其他建议似乎在查询中没有部门名称。此外,我的建议可能具有更好的性能,因为另一个对表进行聚合,再次进行全面扫描,然后与IN 子句进行比较。而我提供的只是做子选择和几个小连接。 这比 Postgres 中需要的复杂得多。 确实提供了另一种解决方案,可以让多个同行共享每间公寓的最高工资。目前尚不清楚 OP 到底想要什么。但我对它不太满意。我在答案中添加了一个更简单的版本。【参考方案3】:

这是参考你的小提琴:

SELECT * -- or whatever is your columns list.
  FROM employees e JOIN departments d ON e.Department_ID = d.id
 WHERE (e.Department_ID, e.Salary) IN (SELECT Department_ID, MAX(Salary)
                                         FROM employees
                                     GROUP BY Department_ID)

编辑:

正如下面评论中提到的,如果您还想查看 IT 部门,所有NULL 用于员工记录,您可以使用RIGHT JOIN 并将过滤条件放在加入子句本身中,如下所示:

SELECT e.name, e.salary, d.name -- or whatever is your columns list.
  FROM employees e RIGHT JOIN departments d ON e.Department_ID = d.id
   AND (e.Department_ID, e.Salary) IN (SELECT Department_ID, MAX(Salary)
                                         FROM employees
                                     GROUP BY Department_ID)

【讨论】:

但不会为 IT 部门返回任何东西。 那是因为IT部门没有员工记录!将员工记录放入 IT 部门,您会看到它有效。 是的,我知道。 :-) 我很想知道(如问题中所述)您将如何返回一行,说明 IT 部门的情况,即员工是 null,薪水也是。 这是个好问题。我会回答这个问题。请将此条款作为对您问题的修改,以便所有人都能看到。 谢谢!我已经编辑了原始问题以使其更加明确,我希望它会更好。【参考方案4】:

好老的经典sql:

select e1.name, e1.salary, e1.department_id
from employees e1
where e1.salary=
  (select maxsalary=max(e.salary)  --, e. department_id
     from employees e 
     where e.department_id = e1.department_id 
   group by e.department_id
   )

【讨论】:

【参考方案5】:

Table1 是 emp - empno、ename、sal、deptno

Table2 是 dept - deptno, dname。

查询可能是(包括 11.2g 上的关系和运行):

select e1.empno, e1.ename, e1.sal, e1.deptno as department

from emp e1

where e1.sal in 

(SELECT  max(sal) from emp e, dept d where e.deptno = d.deptno group by d.dname)

 order by e1.deptno asc; 

【讨论】:

【参考方案6】:
SELECT 
    e.first_name, d.department_name, e.salary 
FROM 
    employees e 
JOIN 
    departments d 
ON 
    (e.department_id = d.department_id) 
WHERE 
    e.first_name 
IN
    (SELECT TOP 2 
        first_name 
    FROM 
        employees
    WHERE 
        department_id = d.department_id);

【讨论】:

【参考方案7】:
`select d.Name, e.Name, e.Salary from Employees e, Departments d,
(select DepartmentId as DeptId, max(Salary) as Salary
from Employees e
group by DepartmentId) m
where m.Salary = e.Salary
and m.DeptId = e.DepartmentId
and e.DepartmentId = d.DepartmentId`

每个部门的最高工资是在内部查询中使用 GROUP BY 计算的。然后选择满足这些限制条件的员工。

【讨论】:

【参考方案8】:

假设 Postgres

返回带有员工详细信息的最高薪水,假设表名 emp 具有带 dept_id 的员工部门

select e1.* from emp e1  inner join (select max(sal) avg_sal,dept_id from emp group by dept_id) as e2 on e1.dept_id=e2.dept_id and e1.sal=e2.avg_sal

【讨论】:

【参考方案9】:

返回每个部门工资最高的一个或多个人:

SELECT result.Name Department, Employee2.Name Employee, result.salary Salary 
FROM ( SELECT dept.name, dept.department_id, max(Employee1.salary) salary 
       FROM Departments dept 
       JOIN Employees Employee1 ON Employee1.department_id = dept.department_id 
       GROUP BY dept.name, dept.department_id ) result 
JOIN Employees Employee2 ON Employee2.department_id = result.department_id 
WHERE Employee2.salary = result.salary

【讨论】:

【参考方案10】:

SQL 查询:

select d.name,e.name,e.salary
from employees e, depts d
where e.dept_id = d.id
and (d.id,e.salary) in
(select dept_id,max(salary) from employees group by dept_id);

【讨论】:

【参考方案11】:

看看这个解决方案 选择 最大(E.SALARY), 姓名, D.NAME 作为部门 来自员工 E 内部连接 ​​D.ID = E.DEPARTMENT_ID 上的 DEPARTMENTS 按 D.NAME 分组

【讨论】:

e.name 将返回部门中的名字,而不是与最高薪水关联的名称。这是由于聚合函数的性质,我害怕

以上是关于部门工资最高的员工的主要内容,如果未能解决你的问题,请参考以下文章

350部门工资最高的员工

184. 部门工资最高的员工

文巾解题 184. 部门工资最高的员工

如何找到每个部门工资最高的员工? [复制]

MySQL部门工资最高的员工

Leetcode No.184 部门工资最高的员工