sql count性能问题

时间:2014-01-19 12:06:56

标签: sql sql-server sql-server-2000

我有两张表用于存储员工出勤详情。

一个表存储emp Id以及相应的时间和日期时间信息第二个表存储其他员工详细信息作为员工ID,员工姓名等... 我需要生成一个报告,该报告显示按每天​​工作的总小时数,状态列存储详细信息,例如,如果总小时数> 4.5否则缺席 还需要计算员工当前状态的天数,员工总小时数大于6小于8.5的天数。

我已经编写了查询来获取每个细节,但性能是不可接受的,需要大约30-35分钟才能获取所有细节

如果我排除计算逻辑的日期大约需要1-2分钟

表结构是

Ist员工表 EmployeeID,EmployeeName .....其他细节(此刻不需要)

出勤表

Emp_ID,INOUT_Time

我的查询

DECLARE @currStartDate DATETIME
DECLARE @currEndDate DATETIME
declare @startDate datetime;
declare @endDate datetime;

set @startDate = CONVERT(Datetime, '12/16/2013');
set @endDate = CONVERT(Datetime, '01/16/2014');

SET @currStartDate=@startDate
SET @currEndDate=dateAdd(day,1,@startDate)

DECLARE @formatTable TABLE
        (
            EmployeeCode varchar(10),
            EmployeeName varchar(100),
            [Date] Datetime,
            InTime datetime,
            OutTime datetime,
            TotalHrs varchar(10),
            [Status] varchar(10)
        )

WHILE @currEndDate <= @endDate
BEGIN
--get the day by day attendance Range
INSERT INTO @formatTable 
(
    EmployeeCode,
    EmployeeName,
    [Date],
    InTime,
    OutTime
)

SELECT
     E.EmployeeID,
    ISNULL(LTRIM(RTRIM(E.FirstName)),'') +' '+ISNULL(LTRIM(RTRIM(E.LastName)),'') AS EmployeeName,
    @currStartDate,
    MIN(AD.INOUT_Time)  as INTIME,
    CASE WHEN MAX(AD.INOUT_Time)=MIN(AD.INOUT_Time) THEN NULL ELSE  MAX(AD.INOUT_Time) END  as OUTTIME
    FROM employees E WITH(NOLOCK)
    LEFT OUTER JOIN Attendance AD
         ON E.EmployeeID = AD.Emp_ID
         AND INOUT_Time BETWEEN @currStartDate AND @currEndDate
        GROUP BY E.EmployeeID,DATEADD(dd, 0, DATEDIFF(dd, 0, INOUT_Time )) 

       UPDATE @formatTable

       SET TotalHrs=Convert(varchar(20),DATEDIFF(MINUTE, ISNULL(InTime,GETDATE()),ISNULL(OutTime,InTime))/Convert(decimal(4,2),60))    
        ,[Status] =(CASE WHEN DATEDIFF(MINUTE, ISNULL(InTime,GETDATE()),ISNULL(OutTime,InTime))/Convert(decimal(4,2),60) >= 4.5
                        THEN 'P'                           
                        ELSE 'Abs' END )
        ,HoursStatus = (CASE WHEN DATEDIFF(MINUTE, ISNULL(InTime,GETDATE()),ISNULL(OutTime,InTime))/Convert(decimal(4,2),60) >= 8.5 
                        THEN 'Greater Than 8.5'
                             WHEN DATEDIFF(MINUTE, ISNULL(InTime,GETDATE()),ISNULL(OutTime,InTime))/Convert(decimal(4,2),60) BETWEEN 6 AND 8.49
                        THEN '6-8.49'
                             WHEN DATEDIFF(MINUTE, ISNULL(InTime,GETDATE()),ISNULL(OutTime,InTime))/Convert(decimal(4,2),60) BETWEEN 4.5 AND 5.99
                        THEN '4.5-5.99' end)

        WHERE [Date]=@currStartDate 
                   -- moving to nextday
       SELECT @currStartDate=DATEADD(DAY,1,@currStartDate)
       SELECT @currEndDate=DATEADD(DAY,1,@currEndDate) 
 END

     IF OBJECT_ID('tempdb..##output') IS NOT NULL
        DROP TABLE ##output

     SELECT EmployeeCode,EmployeeName,[Date],Convert(varchar(10),INTime,108) INTime,Convert(varchar(10),Outtime,108) Outtime,TotalHrs,[Status],Convert(varchar,@startDate,105) as StartDate,Convert(varchar,@endDate,105) as EndDate, (SELECT COUNT(*) FROM @formatTable counter 
           WHERE ft.EmployeeCode = counter.EmployeeCode AND counter.[Status] = 'P' ) AS TotalPresent, (SELECT COUNT(*) FROM @formatTable counter 
           WHERE ft.EmployeeCode = counter.EmployeeCode AND counter.HoursStatus  = 'Greater Than 8.5' ) as gt8point5,(SELECT COUNT(*) FROM @formatTable counter 
           WHERE ft.EmployeeCode = counter.EmployeeCode AND counter.HoursStatus  = '6-8.49' ) as gt6lessthan8,(SELECT COUNT(*) FROM @formatTable counter 
           WHERE ft.EmployeeCode = counter.EmployeeCode AND counter.HoursStatus  = '4.5-5.99' ) as gt4point5lessthan6
     INTO ##output FROM @formatTable as ft
     GROUP BY EmployeeCode,EmployeeName,[Date],TotalHrs,INTime,Outtime,[Status]

     SELECT * FROM ##output AS AttendanceReport

任何提高性能的建议,尤其是日计数逻辑

1 个答案:

答案 0 :(得分:0)

快速查看您的查询会显示以下索引。

-- Assuming you don't have EmployeeID as a clustered index
CREATE INDEX IX_Employees_EmployeeID 
             ON Employees (EmployeeID)
                  INCLUDE (FirstName, LastName)

CREATE INDEX IX_Attendance_EmployeeID_INOUTTime
             ON Attendance (EmployeeID, INOUT_Time)

您还可以为@formatTable创建索引,但这取决于您的查询计划所声明的内容以及生成的行数。