2015-04-01 115 views
0

我正在研究時間表管理的Web應用程序。我編寫了一個查詢,按周將員工的所有時間輸入分組。而且我也必須使用分頁。查詢速度已經很慢,例如數據庫中有10個條目,它需要2-3秒才能運行。SQL Server時間表查詢性能

查詢使用兩個表。 TimeEntry代表一個工作日,當員工開始工作,完成工作並暫停時(TimeEntry.Pause)。

我用這個表按星期分組,我按天計算(星期一,星期二等) TimeType只是一種小時。

第二個表格代表公司在給定的一週內爲員工支付多少時間。

只有PK被索引。

在第二圖像,你可以在這裏看到的結果列:

  • FirstDayOfTheWeek

  • LastDayOftheWeek

  • SumByDayWeek每個

  • HT給予總工作時間本週

  • 惠普給他多少小時已付

  • HB給他多少小時在是時間銀行本週

  • HB TOT。給他多少小時在是時間銀行,直到開始

我想有一些提示,以儘可能多的優化這個查詢越好!

這裏是SQL模式:

schema

下面是結果的一個例子:

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

執行計劃和信息和現有的索引將是解決您的問題最有幫助的事情。 – 2015-04-01 01:11:19

+0

這可能會更好地服務於dba.stackexchange.com – NotMe 2015-04-01 01:22:03

+0

我添加一個鏈接來下載執行計劃。唯一的索引列是PK。我將嘗試在dba.stackechange.com上發佈我的問題 – 2015-04-01 01:29:27

回答

0

難道是計算太多的東西,在插入一個好主意? (coalesce(twe.CCQPaidHour,0)* 60 + coalesce(twe.CCQPaidMinute,0) - (coalesce(twe.CCQAdjustementHour,0)* 60 + coalesce(twe.CCQAdjustementMinute,0)(012) )))。 我只是擦除所有這些領域,並在插入計算它?