SQL Server时间表查询性能

时间:2015-04-01 00:45:11

标签: sql sql-server sql-server-2012

我正在开发一个用于时间表管理的webapp。我写了一个查询,按周分组员工的所有时间。我还必须使用分页。查询已经很慢,数据库中的10个条目需要2-3秒才能运行。

查询使用两个表。 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

1 个答案:

答案 0 :(得分:0)

计算插入物中的大部分内容会不是一个好主意? 我解释而不是做类似的事情 sum(coalesce(twe.CCQPaidHour,0)* 60 + coalesce(twe.CCQPaidMinute,0) - (coalesce(twe.CCQAdjustementHour,0)* 60 + coalesce(twe.CCQAdjustementMinute,0)))。 我只是擦除所有这些字段并在插入中计算它?