薪水高于其部门平均水平的员工 - 已优化

时间:2015-07-27 17:22:40

标签: sql sql-server tsql

我们的数据库中只有一个名为EMPLOYEESALARY的表,其中包含以下3列:

Employee_ID, Employee_Salary, Department_ID

现在我必须选择薪水高于其部门AVERAGE的每位员工。我该怎么做?

我知道这是一个重复的问题,但我发现最好的解决方案是:

SELECT * from employee join (SELECT AVG(employee_salary) as sal, department_ID 
FROM employee GROUP BY Department_ID) as t1 
ON employee.department_ID = t1.department_ID 
where employee.employee_salary > t1.sal

我们可以进一步优化它并在没有子查询的情况下进行优化吗?

参考:

SELECT every employee that has a higher salary than the AVERAGE of his department

Employees with higher salary than their department average?

在此处查找架构,以测试: SQL Fiddle

2 个答案:

答案 0 :(得分:5)

  

我们可以在没有子查询的情况下完成吗?

不是我能想到的。如果条件为>=,则以下内容将起作用

SELECT TOP 1 WITH TIES *
FROM   employee
ORDER  BY CASE
            WHEN employee_salary >= AVG(employee_salary)
                                     OVER (
                                       PARTITION BY Department_ID) THEN 0
            ELSE 1
          END 

但是这不是优化,如果没有员工的工资大于平均水平(即所有员工都是),那么它对>条件无法正常工作部门有相同的工资)

  

我们可以进一步优化吗?

您可以使用

缩短语法
WITH T AS
(
 SELECT *,
       AVG(employee_salary) OVER (PARTITION BY Department_ID)  AS sal
FROM   employee
)
SELECT *
FROM T
WHERE  employee_salary > sal

但它仍然需要做同样的工作。

假设基表上已存在合适的索引,那么在SELECT时间避免一些更多工作的唯一方法是预先计算分组SUMCOUNT_BIG in由Department_ID分组的索引视图(以便能够廉价地推导出平均值)。

答案 1 :(得分:1)

更优化的形式可能是:

select e.*
from (select e.*, avg(employee_salary) over (partition by department_id) as avgs
      from employee e
     ) e
where employee_salary > avgs;

此(以及其他版本)可以使用employee(department_id, employee_salary)上的索引。最终的where可能不应该使用索引,因为它选择了很多行。