部门工资最高的员工
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?
除此之外:使用非描述性列名(如 name
或 id
)是一种反模式。应该是employee_id
、employee
等。
返回所有个每个部门薪水最高的员工。
使用窗口函数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 将返回部门中的名字,而不是与最高薪水关联的名称。这是由于聚合函数的性质,我害怕以上是关于部门工资最高的员工的主要内容,如果未能解决你的问题,请参考以下文章