我们的数据库中只有一个名为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
答案 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
时间避免一些更多工作的唯一方法是预先计算分组SUM
和COUNT_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
可能不应该使用索引,因为它选择了很多行。