[英]SQL Server Timesheet Query Performance
我正在開發用於時間表管理的webapp。 我編寫一個查詢,以按周對員工的所有時間條目進行分組。 而且我還必須使用分頁。 查詢已經很慢,在數據庫中有10個條目,運行了2-3秒。
該查詢使用兩個表。 TimeEntry代表員工上班,下班時的休息日和工作暫停時間(TimeEntry.Pause)。
我使用此表按周分組,並按天(周一,周二等)進行總和。TimeType只是一種小時。
第二張表代表公司在給定一周內支付給員工多少時間。
僅PK被索引。
在第二張圖片中,您可以在列中看到結果:
本周第一天
一周的最后一天
每個SumByDayWeek
HT給出一周的總工作時間
惠普給他多少小時的報酬
HB給他這星期有多少小時
HB TOT。 給他多少時間,直到開始
我想要一些技巧來盡可能優化此查詢!
這是sql模式:
這是結果的示例:
結果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
計算插入內容中的很多內容是個好主意嗎? 我解釋而不是做諸如sum(coalesce(twe.CCQPaidHour,0)* 60 + coalesce(twe.CCQPaidMinute,0)-(coalesce(twe.CCQAdjustementHour,0)* 60 + Coalesce(twe.CCQAdjustementHour,0)* 60 )。 我只是擦除所有這些字段並在插入中計算出來?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.