I have a query that looks like the following, it is just entirely too slow and I don't know how to speed it up. This query is currently correlated. Will a temp table to then join solve this?
SELECT
e.ID, e.Name
FROM
Employees e
WHERE
e.Salary > (SELECT AVG(e2.Salary)
FROM Employees e2
WHERE e2.DepartmentID = e.DepartmentID)
Please try following SQL query
with cte as (
select
*,
AVG(Salary) over (partition by DepartmentID) average
from employees
)
select * from cte where Salary > average
Here you will see that I used SQL Average aggregation function with Partition By clause In order to use it I preferred a SQL CTE expression
I would try moving the sub query into a join. If there is an index on the DepartmentID
that includes the salary column, then it will produce the subquery result quickly and join it to the main results.
SELECT e.ID,
e.Name
FROM Employees e
INNER JOIN (
SELECT DepartmentID, AVG(Salary) as AverageSalary
FROM Employees
GROUP BY DepartmentId
) dptAvg ON e.DepartmentID = dptAvg.DepartmentId
WHERE
e.Salary > dptAvg.AverageSalary
It's not just the select, think of the usecase. You need to calculate the average salary just when you add or update an employee's salary, but you could need this query more often. There's no point in recalculating each time you do a read.
I would separate the second query, store the result in the Departments
table (I'm assuming you have one) in a field called AvgSalary
and then have the query look like:
SELECT
e.ID,
e.Name
FROM
Employees e
JOIN Departments d ON e.DepartmentID = d.DepartmentID
WHERE
e.Salary > d.AvgSalary
At first I suggest you to try CROSS APPLY here is some more info:
SELECT e.ID,
e.Name
FROM Employees e
CROSS APPLY (
SELECT AVG(e2.Salary) as avgs
FROM Employees e2
WHERE e2.DepartmentID = e.DepartmentID
) as p
WHERE e.Salary > avgs
If you are using SQL Server 2012 and up then you can use CTE with AVG OVER
;WITH cte AS (
SELECT e.ID,
e.Name,
AVG(e.Salary) OVER (PARTITION BY e.DepartmentID ORDER BY e.ID) as avgs,
e.Salary
FROM Employees e
)
SELECT ID,
Name
FROM cte
WHERE Salary > avgs
Pre-Calculate the average salary for each department and use it in further queries.
SELECT AVG(e2.Salary) as avgSalary,DepartmentID into #t
FROM Employees
group by DepartmentID
SELECT e.ID,
e.Name
FROM
Employees e
WHERE
e.Salary > (
SELECT avgSalary
FROM #t e2
WHERE e2.DepartmentID = e.DepartmentID)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.