簡體   English   中英

SQL Server時間表查詢性能

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM