【问题标题】: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?

标签: sql postgresql


【解决方案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 将返回部门中的名字,而不是与最高薪水关联的名称。这是由于聚合函数的性质,我害怕
                  猜你喜欢
                  • 2019-01-25
                  • 2016-06-20
                  • 1970-01-01
                  • 2019-06-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-08-02
                  • 2020-08-09
                  相关资源
                  最近更新 更多