这是选择:
SELECT e.Id AS EmployeeId,
ISNULL(
SUM(CASE
WHEN DATEDIFF(MINUTE, o.StartDate, o.EndDate) < 360
THEN DATEDIFF(MINUTE, o.StartDate, o.EndDate)
WHEN DATEDIFF(MINUTE, o.StartDate, o.EndDate) < 560
THEN DATEDIFF(MINUTE, o.StartDate, o.EndDate) - 20
ELSE
DATEDIFF(MINUTE, o.StartDate, o.EndDate) - 45
END), 0) AS OvertimeSum
FROM
Overtimes o
RIGHT OUTER JOIN Employees e ON o.EmployeeId = e.Id
INNER JOIN Groups g ON g.Id = e.GroupId
WHERE
(((CONVERT(DATE, o.StartDate) >= @StartDate) AND
(CONVERT(DATE, o.StartDate) <= @EndDate)) OR
(o.StartDate IS NULL)) AND
(g.ShiftModelId = @ShiftModelId)
GROUP BY e.Id
我认为是select子句。它太长了,例如可以将DATEDIFF(MINUTE, o.StartDate, o.EndDate)
带入变量或其他东西。
答案 0 :(得分:0)
正如Joe W在评论中提到的那样,你可以将常见的约会移动到一个共同的表达式,以简化一些事情,例如(未经测试的);
WITH cte AS (
SELECT e.Id AS EmployeeId, DATEDIFF(MINUTE, o.StartDate, o.EndDate) Overtime
FROM
Overtimes o
RIGHT OUTER JOIN Employees e ON o.EmployeeId = e.Id
INNER JOIN Groups g ON g.Id = e.GroupId
WHERE
(((CONVERT(DATE, o.StartDate) >= @StartDate) AND
(CONVERT(DATE, o.StartDate) <= @EndDate)) OR
(o.StartDate IS NULL)) AND
(g.ShiftModelId = @ShiftModelId)
)
SELECT EmployeeId, ISNULL(SUM(CASE WHEN Overtime < 360 THEN Overtime
WHEN Overtime < 560 THEN Overtime - 20
ELSE Overtime - 45
END), 0) AS OvertimeSum
FROM cte
GROUP BY EmployeeId
答案 1 :(得分:0)
在执行JOIN之前划分查询并对各个表应用过滤器。更新Local Variable的数据类型以匹配表中的Column Type数据。在WHERE条件中使用左侧列上的函数不好,并且索引不会用于此类查询。在你的情况下,该声明是:
CONVERT(DATE,o.StartDate)&gt; = @StartDate
CONVERT(DATE,o.StartDate)&lt; = @EndDate
而是将@StartDate更新为Datetime或o.StartDate的任何列类型。我发现你需要只比较日期而不是时间部分,所以在使用它进行查询之前,用零时间部分更新/添加传入的本地参数值。和@EndDate一样。
确保您在Overtimes.StartDate列上有索引。我不确定你有什么其他索引。或者您对此表有哪些其他类型的查询,但
如果CLUSTERED那么(Overtimes.StartDate,Overtimes.EmployeeId)
覆盖非群集然后(Overtimes.StartDate)包括(EmployeeId)
表表员工和组确保您具有类似的索引。
群集/非群集 - &gt; (Groups.ShiftModelId,Groups.ID)和(Employees.GroupID)
然后尝试此查询
SELECT EmployeeId,OvertimeSum
FROM
(
SELECT o.EmployeeId AS EmployeeId ,
ISNULL(SUM(CASE WHEN DATEDIFF(MINUTE, o.StartDate, o.EndDate) < 360
THEN DATEDIFF(MINUTE, o.StartDate, o.EndDate)
WHEN DATEDIFF(MINUTE, o.StartDate, o.EndDate) < 560
THEN DATEDIFF(MINUTE, o.StartDate, o.EndDate) - 20
ELSE DATEDIFF(MINUTE, o.StartDate, o.EndDate) - 45
END), 0) AS OvertimeSum
FROM Overtimes o
WHERE ( o.StartDate IS NULL ) OR ( o.StartDate BETWEEN @StartDate AND @EndDate )
GROUP BY o.EmployeeId
)q1
RIGHT OUTER JOIN
(
SELECT e.ID AS EmployeeId
FROM Employees e
INNER JOIN Groups g ON g.Id = e.GroupId
AND g.ShiftModelId = @ShiftModelId
)q2
ON q1.EmployeeId=q2.EmployeeId