2015-04-01 68 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) )))。 我只是擦除所有这些领域,并在插入计算它?