简体   繁体   English

相关SQL Server查询的性能问题

[英]Performance issue with correlated SQL Server query

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 请尝试以下SQL查询

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 在这里,您将看到我将SQL Average 聚合函数与Partition By子句一起使用。为了使用它,我更喜欢使用SQL CTE表达式

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. 如果DepartmentID上有一个包含薪金列的索引,则它将快速生成子查询结果并将其与主要结果连接。

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: 我将分开第二个查询,将结果存储在名为AvgSalary的字段中的Departments表中(假设您有一个),然后使查询看起来像:

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: 首先,我建议您尝试CROSS APPLY, 这里提供了更多信息:

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 如果您使用的是SQL Server 2012及更高版本,则可以将CTE与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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM