【发布时间】:2015-07-20 01:21:14
【问题描述】:
此查询已运行了数小时,正在寻求帮助以提高效率。我玩过,似乎让它运行如此缓慢的是 WHERE 子句的最后一部分:
"AND emp.employee_ID NOT IN <subquery with INNER JOINS and WHERE clause>".
如果我注释掉那部分,它会在几秒钟内返回,但不幸的是我需要从父查询中省略这些记录,所以我需要一些逻辑来做到这一点。任何其他方法表示赞赏。 SQL 查询分析器建议在employeejob 表上建立索引。
我无法更改选择列表,此查询将数据发送到网站,并且必须采用该确切格式。
此查询不只运行一次。它的 select 子句会略有不同(例如,Part Time 将更改为 Full Time),它将在循环中再次运行。 @Reporting_Date 将更改为另一个月份,它将在循环内再次运行。总而言之,此查询将运行数十次(在几个月的系列中,每个月的指标略有不同,例如 Part Time、Full Time、Exempt、Non Exempt)。我将循环逻辑排除在外,因为它基本上是相同的查询重复。对于一个指标,每月返回一次似乎需要几个小时。
这是确切的代码:
DECLARE @Reporting_Date varchar(20)
DECLARE @Metric_Date varchar(20)
DECLARE @Begin_Date varchar(20)
DECLARE @End_Date varchar(20)
SET @Reporting_Date = cast('02/01/2015' as datetime)
SET @Metric_Date = convert(varchar,dateadd(m, -1 ,@Reporting_Date),112)
SET @Begin_Date = convert(varchar,dateadd(m, -1 ,@Reporting_Date),112)
SET @End_Date = convert(varchar,dateadd(d, -1 ,@Reporting_Date),112)
select @Metric_Date as MetricPeriod
,org.locationnameid
,dep.divisionid
,ej.jobdepartmentid
,1
,' Part Time'
,3
,Count(*)
from ddw.dbo.Employee emp
inner join dbo.Organization org on org.organizationid = emp.organizationid and org.orgid in ('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
inner join dbo.status st on st.statusid = emp.statusid and st.statuscode not in ('T','X','N')
inner join dbo.employeejob ej on ej.employeeid = emp.employeeid and ej.jobnumber = '1' and ej.SnapShotDate = @Metric_Date
inner join dbo.department dep on dep.departmentid = ej.jobdepartmentid
where
ej.percentfulltime between '2.00' and '89.00'
AND
emp.SnapShotDate = @Metric_Date
**AND
emp.Employee_ID not IN
(
select Employee_ID
from dbo.Employee_Terms_All terms
inner join dbo.Organization org on org.organizationid = terms.organizationid and org.orgid in ('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
inner join dbo.terminationreasoncode trc on trc.terminationreasoncodeid = terms.terminationreasoncodeid and trc.terminationreasoncode not in ('4','5','6')
inner join dbo.department dep on dep.departmentid = terms.jobdepartmentid
where terms.terminationdate between @Begin_Date and @End_Date
)**
group by
org.locationnameid
,dep.divisionid
,ej.jobdepartmentid
order by
org.locationnameid
,dep.divisionid
,ej.jobdepartmentid
感谢您的任何想法!
【问题讨论】:
-
有大量的内部连接和嵌套查询,这就是为什么它需要永远。对连接进行连接会导致你做噩梦
-
另外,您的 orgid in 子句正在检查字母表中的每个字母。可能的值是多少?
-
所以添加建议的索引.. 会发生什么? (注意查询的“非索引”/建议替换部分所花费的时间百分比 - 如果它很重要,那么它显然是第一轮获胜者。)
-
您可以尝试的方法(它可能会使事情变得更糟,但您想尝试一下),就是将
NOT IN重新表述为NOT EXISTS。为此,您需要在 NOT EXISTS 之后将 `AND Employee_id = emp.Employee_ID ` 添加到括号内的WHERE。对于这可能有助于您的查询,Employee_ID(可能在 Employee_Terms_All 中)有一个索引是非常重要的。 -
请参阅this answer 重新交换 LEFT JOIN、NOT EXISTS 和 NOT IN。如果可用,您还可以使用标准 SQL EXCEPT aka Oracle MINUS。
标签: sql-server subquery inner-join