我正在开发一个用于时间表管理的webapp。我写了一个查询,按周分组员工的所有时间。我还必须使用分页。查询已经很慢,数据库中的10个条目需要2-3秒才能运行。
查询使用两个表。 TimeEntry表示员工开始工作时的工作日,以及他完成工作的时间和他在一分钟内暂停的时间(TimeEntry.Pause)。
我使用这个表按周分组,我按天(星期一,星期二等)做一笔钱... TimeType只是一种时间。
第二张表格表示公司在一周内为员工支付的时间。
只有PK被编入索引。
在第二张图片中,您可以在此处看到结果:
FirstDayOfTheWeek
LastDayOftheWeek
每个
HT给出一周的总工作时间
惠普提供了多少小时的工资
HB给出他本周时间银行的小时数
HB TOT。给他们在时间银行里开了多少小时直到开始
我希望尽可能多地优化此查询!
这是sql架构:
以下是结果示例:
result http://s12.postimg.org/gbwc1wiqz/image.png
这是执行计划:
ALTER PROCEDURE [dbo].[TimesheetWeek_Employee_Search]
@pPageNumber int,
@pEmployeeID int
AS
BEGIN
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE @Count int
DECLARE @PageCount int
DECLARE @TmpTimesheetWeekEmployee TABLE(FirstDayOfWeek DateTime, CCQPaidHour int, CCQPaidMinute int, STAFFPaidHour int, STAFFPaidMinute int,
CCQAdjustementHour int, CCQAdjustementMinute int, STAFFAdjustementHour int, STAFFAdjustementMinute int)
Insert into @TmpTimesheetWeekEmployee(FirstDayOfWeek, CCQPaidHour, CCQPaidMinute, STAFFPaidHour, STAFFPaidMinute,
CCQAdjustementHour, CCQAdjustementMinute, STAFFAdjustementHour, STAFFAdjustementMinute)
select FirstDayOfWeek, CCQPaidHour, CCQPaidMinute, STAFFPaidHour, STAFFPaidMinute,
CCQAdjustementHour, CCQAdjustementMinute, STAFFAdjustementHour, STAFFAdjustementMinute
from TimesheetWeekEmployee
where EmployeeID = @pEmployeeID
DECLARE @TmpTimeEntry TABLE(ID int, TimesheetID int, StartTime DateTime, EndTime DateTime, [Pause] int, TimeTypeID int)
Insert into @TmpTimeEntry(ID, TimesheetID, StartTime, EndTime, [Pause], TimeTypeID)
select ID, TimesheetID, StartTime, EndTime, [Pause], TimeTypeID
from TimeEntry
where EmployeeID = @pEmployeeID
select @Count = (select count(*) from (select 1 C
from @TmpTimeEntry TimeEntry
group by dbo.FirstDayOfWeek(StartTime), dbo.LastDayOfWeek(StartTime)) TE);
select @PageCount = (case when @Count % 10 = 0 then @Count / 10
when @Count < 10 then 1
else @Count / 10 + 1 end)
select eID, CONVERT(char(10), TSW.FirstDayOfWeek ,126)FirstDayOfWeek, LastDayOfWeek,
MinuteCCQ, LundiCCQ, MardiCCQ, MercrediCCQ, JeudiCCQ, VendrediCCQ, SamediCCQ,
sum(coalesce(TotalCCQ,0)) TotalCCQBefore,
MinuteSTAFF, LundiSTAFF, MardiSTAFF, MercrediSTAFF, JeudiSTAFF, VendrediSTAFF, SamediSTAFF,
sum(coalesce(TotalSTAFF,0)) TotalSTAFFBefore,
@pEmployeeID EmployeeID,
@PageCount 'PageCount',
coalesce(TWET.TotalCCQPaid, 0) 'TotalCCQPaid',
coalesce(Twet.TotalSTAFFPaid, 0) 'TotalSTAFFPaid',
coalesce(TWE.CCQPaid, 0) CCQPaid,
coalesce(TWE.STAFFPaid, 0) STAFFPaid
from (select dbo.Encrypt( ROW_NUMBER() over(order by dbo.FirstDayOfWeek(StartTime) desc) ) as 'eID',
dbo.FirstDayOfWeek(StartTime) FirstDayOfWeek,
CONVERT(char(10),dbo.LastDayOfWeek(StartTime) ,126) LastDayOfWeek,
Sum(case when TimeTypeID = 3 then DATEDIFF(mi,StartTime,EndTime) - Pause else 0 end) 'MinuteCCQ',
Sum((case when DATEPART(dw,StartTime) = 1 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'LundiCCQ',
Sum((case when DATEPART(dw,StartTime) = 2 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MardiCCQ',
Sum((case when DATEPART(dw,StartTime) = 3 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MercrediCCQ',
Sum((case when DATEPART(dw,StartTime) = 4 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'JeudiCCQ',
Sum((case when DATEPART(dw,StartTime) = 5 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'VendrediCCQ',
Sum((case when DATEPART(dw,StartTime) = 6 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'SamediCCQ',
Sum(case when TimeTypeID = 4 then DATEDIFF(mi,StartTime,EndTime) - Pause else 0 end) 'MinuteSTAFF',
Sum((case when DATEPART(dw,StartTime) = 1 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'LundiSTAFF',
Sum((case when DATEPART(dw,StartTime) = 2 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MardiSTAFF',
Sum((case when DATEPART(dw,StartTime) = 3 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MercrediSTAFF',
Sum((case when DATEPART(dw,StartTime) = 4 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'JeudiSTAFF',
Sum((case when DATEPART(dw,StartTime) = 5 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'VendrediSTAFF',
Sum((case when DATEPART(dw,StartTime) = 6 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'SamediSTAFF'
from @TmpTimeEntry TimeEntry
group by dbo.FirstDayOfWeek(StartTime), dbo.LastDayOfWeek(StartTime)) TSW
left join ( select dbo.FirstDayOfWeek(StartTime) FirstDayOfWeek,
Sum((case when TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - [Pause]) else 0 end)) 'TotalCCQ',
Sum((case when TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - [Pause]) else 0 end)) 'TotalSTAFF'
from @TmpTimeEntry TimeEntry
group by dbo.FirstDayOfWeek(StartTime), dbo.LastDayOfWeek(StartTime)) TT
on TT.FirstDayOfWeek < TSW.FirstDayOfWeek
left join (select E.FirstDayOfWeek,
sum(coalesce(twe.CCQPaidHour,0 )* 60 + coalesce(twe.CCQPaidMinute,0 )-(coalesce(twe.CCQAdjustementHour,0 )* 60 + coalesce(twe.CCQAdjustementMinute,0 ))) 'TotalCCQPaid',
sum(coalesce(twe.STAFFPaidHour,0 ) * 60 + coalesce(twe.STAFFPaidMinute,0 )-(coalesce(twe.STAFFAdjustementHour,0 ) * 60 + coalesce(twe.STAFFAdjustementMinute,0 ))) 'TotalSTAFFPaid'
from (select dbo.FirstDayOfWeek(StartTime) FirstDayOfWeek,
EmployeeID
from TimeEntry
where EmployeeID = @pEmployeeID
group by dbo.FirstDayOfWeek(StartTime), EmployeeID) E
left join @TmpTimesheetWeekEmployee twe on twe.FirstDayOfWeek < e.FirstDayOfWeek
group by E.FirstDayOfWeek) as TWET
on TWET.FirstDayOfWeek = TSW.FirstDayOfWeek
left join (select FirstDayOfWeek,
coalesce(CCQPaidHour,0 )* 60 + coalesce(CCQPaidMinute,0 ) 'CCQPaid',
coalesce(STAFFPaidHour,0 ) * 60 + coalesce(STAFFPaidMinute,0 ) 'STAFFPaid'
from @TmpTimesheetWeekEmployee) as TWE
on dbo.FirstDayOfWeek(TWE.FirstDayOfWeek) = TSW.FirstDayOfWeek
GROUP BY TSW.FirstDayOfWeek, LastDayOfWeek, eID,
MinuteCCQ, LundiCCQ, MardiCCQ, MercrediCCQ, JeudiCCQ, VendrediCCQ, SamediCCQ,
MinuteSTAFF, LundiSTAFF, MardiSTAFF, MercrediSTAFF, JeudiSTAFF, VendrediSTAFF, SamediSTAFF, MinuteSTAFF,
CCQPaid, STAFFPaid, TotalCCQPaid, TotalSTAFFPaid
ORDER BY TSW.FirstDayOfWeek desc
OFFSET (case when @pPageNumber > @PageCount then 1
else (@pPageNumber -1 ) * 10 end) ROWS
FETCH NEXT 10 ROWS ONLY
END
答案 0 :(得分:0)
计算插入物中的大部分内容会不是一个好主意? 我解释而不是做类似的事情 sum(coalesce(twe.CCQPaidHour,0)* 60 + coalesce(twe.CCQPaidMinute,0) - (coalesce(twe.CCQAdjustementHour,0)* 60 + coalesce(twe.CCQAdjustementMinute,0)))。 我只是擦除所有这些字段并在插入中计算它?