如何选择部门的前三名薪水?

时间:2016-02-26 13:49:05

标签: mysql sql

我尝试在线解决有2个表的SQL问题,

员工

Employee表包含所有员工。

+----+-------+--------+--------------+
| Id | Name  | Sa1ary | DepartmentId |
+----+-------+--------+--------------+
|  1 | Joe   |  70000 |            1 |
|  2 | Henry |  80000 |            2 |
|  3 | Sam   |  60000 |            2 |
|  4 | Max   |  90000 |            1 |
|  5 | Janet |  69000 |            1 |
|  6 | Randy |  85000 |            1 |
+----+-------+--------+--------------+

部门

enter image description here

SQL应该返回以下数据

enter image description here

我有以下SQL查询,

    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 DepartmentId = E.DepartmentId AND Salary > E.Salary) < 3
ORDER by E.DepartmentId, E.Salary DESC;

SQL很好,但是,我对< 3部分感到困惑。不应该是关于前3名工资问题的问题= 3吗?我很感激SQL的解释,并会有所帮助。

8 个答案:

答案 0 :(得分:5)

如果您添加了一列Count employees who earn more,那么您的表格将如下所示

+----+-------+--------+--------------+-------------------------------+
| Id | Name  | Sa1ary | DepartmentId | Count employees who earn more |
+----+-------+--------+--------------+-------------------------------+
|  1 | Joe   |  70000 |            1 |    2                          |
|  2 | Henry |  80000 |            2 |    0                          |
|  3 | Sam   |  60000 |            2 |    1                          | 
|  4 | Max   |  90000 |            1 |    0                          |
|  5 | Janet |  69000 |            1 |    3                          |
|  6 | Randy |  85000 |            1 |    1                          |
+----+-------+--------+--------------+-------------------------------+

然后找到每个部门的前3名。你的WHERE将是

WHERE `Count employees who earn more` < 3

如果你有=3,它将返回唯一的第四位

的员工

由于你没有那个列,这就是这个SQL的作用

(SELECT COUNT(DISTINCT(Salary)) FROM Employee 
       WHERE DepartmentId = E.DepartmentId AND Salary > E.Salary)

如果您想制作上述表格,可以执行以下操作

SELECT 
      D.Name AS Department, 
      E.Name AS Employee, 
      E.Salary AS Salary,
      Count(E2.Salary) as Count_employees_who_earn_more
FROM Employee E 
INNER JOIN Department D 
ON E.DepartmentId = D.Id 
LEFT JOIN Employee E2 ON 
    e2.DepartmentId = E.DepartmentId
    AND E2.Salary > E.Salary
GROUP BY  D.Name , 
      E.Name , 
      E.Salary 

Demo

答案 1 :(得分:0)

我正在处理同样的SQL问题。

以防有人可能需要帮助。

这是我想出的答案。

SELECT
    dpt.Name AS Department,
    e1.Name AS Employee,
    e1.Salary AS Salary
FROM Employee AS e1
INNER JOIN Department dpt
ON e1.DepartmentID = dpt.Id
WHERE 3 > (
           SELECT COUNT(DISTINCT Salary)
           FROM Employee AS e2
           WHERE e2.Salary > e1.Salary
           AND e1.DepartmentID = e2.DepartmentID
          )
ORDER BY
Department ASC,
Salary DESC;
  1. 困难的部分是获得每个部门的前3名工资。 我首先计算 [薪水较高的员工人数]

    之后,我使用 3&gt; [薪水较高的员工人数] 仅保留前3名薪水。 (如果前三名中有超过3名员工,也就是说其中一些员工的薪水相同,则所有员工都将被包括在内。)

    查询

    SELECT *
    FROM Employee e1
    WHERE 3 > (
               SELECT COUNT(DISTINCT Salary)
               FROM Employee e2
               WHERE e2.Salary > e1.Salary
               AND e1.DepartmentID = e2.DepartmentID
              );
    

    输出

    +------+-------+--------+--------------+
    | Id   | Name  | Salary | DepartmentId |
    +------+-------+--------+--------------+
    |    1 | Joe   |  70000 |            1 |
    |    2 | Henry |  80000 |            2 |
    |    3 | Sam   |  60000 |            2 |
    |    4 | Max   |  90000 |            1 |
    |    6 | Randy |  85000 |            1 |
    +------+-------+--------+--------------+
    
  2. 然后这是容易的部分。您可以将此表与DepartmentID上的Department一起加入以获取部门名称。

    最终输出

    +------------+----------+--------+
    | Department | Employee | Salary |
    +------------+----------+--------+
    | IT         | Max      |  90000 |
    | IT         | Randy    |  85000 |
    | IT         | Joe      |  70000 |
    | Sales      | Henry    |  80000 |
    | Sales      | Sam      |  60000 |
    +------------+----------+--------+
    

答案 2 :(得分:0)

with sal_CTE as
(
 select e.Id as emp_id,
    d.Name as dept_name,
    e.Name as emp_name,
    e.Salary as emp_sal,
    DENSE_RANK() OVER(PARTITION BY d.ID Order By  e.Salary desc) as rank
 from Employee e inner join department d
 ON (e.DepartmentId = d.Id)
)

select dept_name as Department,
emp_name as Employee,
emp_sal as Salary from sal_CTE
where rank <=3
order by dept_name;

答案 3 :(得分:0)

您可以通过在mysql> 5.7和所有支持窗口功能的主要数据库中使用窗口功能来实现此目的

select  dept_name, emp_name, salary from (
select d.name as dept_name, e.name as emp_name, e.salary, 
rank() over(partition by d.name order by e.salary desc) as rank_count 
from employee e, department d 
where d.id = e.dept_id) a where a.rank_count <4

如果一个表具有空键而另一个表没有映射键,则可以根据需要将内部联接更改为左联接

答案 4 :(得分:0)

另一种实现方式:

WITH table1 AS 
(
    SELECT Department.Name AS Department, Employee.Name AS Employee, Salary
    FROM Employee
    INNER JOIN Department 
    ON DepartmentId = Department.Id
),

table2 AS 
(
    SELECT * FROM ( 
                    SELECT Department, Employee, Salary, DENSE_RANK() OVER                       (PARTITION BY Department ORDER BY Salary DESC) AS rank 
                    FROM table1
                   ) t
    WHERE rank<=3 
)

SELECT Department, Employee, Salary 
FROM table2;

答案 5 :(得分:0)

  SELECT 
  Department, 
  Employee, 
  Salary
  FROM 
  (

  SELECT 
  D.Name AS Department, 
  E.Name AS Employee, 
  E.Salary AS Salary,
  DENSE_RANK() OVER (
  PARTITION BY d.NAME
  ORDER BY d.name, E.SALARY DESC
  ) AS RANK

  FROM Employee E 
  INNER JOIN Department D 
  ON E.DepartmentId = D.Id
  group by d.name, e.name, e.salary
  ) 
  WHERE RANK <= 3

对于Oracle 11G

答案 6 :(得分:0)

dense_rank() works,rank() 会在 2 rowssame salary 之间产生间隙。

with  temp_tbl as (
select d.name as Department,i.name as Employee,Salary,dense_rank() over (partition by departmentid order by salary desc) as rnk
from employee i,department d
where i.departmentid=d.id)
select  Department,Employee,Salary
from temp_tbl
where rnk<4

答案 7 :(得分:-1)

With CTE_EMP AS 
(
Select d.Name AS Department, e.Name as Employee, e.Salary,
 ROW_NUMBER() over (partition by DepartmentId order by Salary desc) AS RowNumber
From Employee e
JOIN Department d on d.Id = e.DepartmentId
)
Select Department, Employee, Salary FROM CTE_EMP Where RowNumber <= 3