如何从日历表中获取列表并合并到考勤表和离开表

时间:2015-11-10 06:05:17

标签: sql sql-server

我正在使用SQL Server 2008 R2。我在合并表时遇到问题。我们有500多名员工

我有以下表格:

  1. Calendar表 - 保留日期为1/1/2005至2016年12月31日
  2. Attendance表 - 供员工出席
  3. LeaveHistory表 - 用于休假历史
  4. LeaveBreakDown table -for leave break down
  5. Holiday表 - 假期
  6. 我们的目标,日期范围从日历(2015年11月1日 - 2015年11月30日) 我们希望显示完整的日子,即使出勤率不等于总天数。

    这是我的第一个解决方案,但速度太慢,没有日历表

     FETCH NEXT FROM Employees INTO @EmployeeID,@BranchCode,@IsOfficer, @FirstName, @MiddleName, @LastName, @RankCode;
    
     WHILE @@FETCH_STATUS = 0
     BEGIN
         WHILE @StartDate <= @EndDate
         BEGIN
            INSERT INTO #tblData(ActualDate,EmployeeID,BranchCode,IsOfficer, FirstName, MiddleName, LastName, RankCode, LeaveCode, Gender, ShiftCode,ShiftIn,ShiftOut,IsRestDay) 
                SELECT
                     @StartDate
                        , @EmployeeID
                        , @BranchCode
                        , @IsOfficer
                        , @FirstName
                        , @MiddleName
                        , @LastName
                        , @RankCode
                        , LB.LeaveBreakDownCode
                        , E.Gender
                    ,ShiftCode = SS.ShiftCode
                    ,ShiftIn = CONVERT(DATETIME, CONVERT(VARCHAR(20), DATEADD(day,0,@StartDate), 101) + ' ' + CONVERT(VARCHAR(20), SS.ShiftIn,108))
                    ,ShiftOut = CASE
                                                                         WHEN SS.ShiftOut < SS.ShiftIn THEN CONVERT(DATETIME, CONVERT(VARCHAR(20), DATEADD(day,1,@StartDate), 101) + ' ' + CONVERT(VARCHAR(20), SS.ShiftOut ,108))
                                                                         ELSE CONVERT(DATETIME, CONVERT(VARCHAR(20), DATEADD(day,0,@StartDate), 101) + ' ' + CONVERT(VARCHAR(20), SS.ShiftOut ,108))
                                                                    END
                    ,IsRestDay = CASE
                                                                                WHEN SS.Sunday = 1 AND DATEPART(weekday, @StartDate) = 1 THEN 1
                                                                                WHEN SS.Monday = 1 AND DATEPART(weekday, @StartDate) = 2 THEN 1
                                                                                WHEN SS.Tuesday = 1 AND DATEPART(weekday, @StartDate) = 3 THEN 1
                                                                                WHEN SS.Wednesday = 1 AND DATEPART(weekday, @StartDate) = 4 THEN 1
                                                                                WHEN SS.Thursday = 1 AND DATEPART(weekday, @StartDate) = 5 THEN 1
                                                                                WHEN SS.Friday = 1 AND DATEPART(weekday, @StartDate) = 6 THEN 1
                                                                                WHEN SS.Saturday = 1 AND DATEPART(weekday, @StartDate) = 7 THEN 1                      
                                                                                ELSE 0
                                                                            END
                        FROM Employees E
                        LEFT JOIN (
                            SELECT
                            LB.LeaveBreakDownCode
                            , LB.EmployeeID
                            FROM LeaveBreakDown LB
                            INNER JOIN LeaveHistory LH ON LH.LeaveHistoryCode = LB.LeaveHistoryCode AND LB.DateLeave = @StartDate AND LH.Status IN ('0','1')
                            WHERE LB.EmployeeID = @EmployeeID                                           
                        ) LB ON LB.EmployeeID = E.EmployeeID                        
                        LEFT JOIN ShiftSchedule SS ON SS.EmployeeID = E.EmployeeID AND @StartDate BETWEEN SS.EffectivityDate AND SS.EndDate
                        WHERE E.Status='1' AND E.ResignedDate IS NULL AND E.EmployeeID =    @EmployeeID        
           SET @StartDate = DATEADD(day,1,@StartDate)
          END       
        SET @StartDate   = @InitialDate -- Reinitialize Start Date
     FETCH NEXT FROM Employees INTO @EmployeeID, @BranchCode,@IsOfficer,@FirstName, @MiddleName, @LastName, @RankCode;
     END;
    

    关闭员工; DEALLOCATE员工;

    使用此解决方案,如果我们要运行脚本。花了3分钟,有时是6分钟。

    可能是结构

    日期(&#39; 11/1 / 2015&#39; - &#39; 11/30/2015&#39;)   - &GT;勤   - &GT; LeaveHistory

    日期范围中日期表的所有日期都将填入来自不同表格的值。

1 个答案:

答案 0 :(得分:0)

  1. 不要使用游标。事实上,它可以在不使用RBAR /游标的情况下完成。
    1. 你需要解释一下你的桌面结构。或者用较少的列和表来慢慢开始,并询问你被击中的地方。
    2. 日历表不是必需的。&#34; ShiftSchedule&#34;的目的是什么? ?
    3. 您可以使用递归CTE来完成此操作。
    4. 告诉我们更多信息,然后我们会相应地帮助您。
  2. 递归CTE样本。你可以用更少的表和列来实现你的例子然后逐渐增加。

    DECLARE @StartDate DATETIME = '11/1/2015'
    DECLARE @EndDate DATETIME = '11/30/2015';
    
    WITH CTE
    AS (
        SELECT @StartDate DT
    
        UNION ALL
    
        SELECT DATEADD(day, 1, DT)
        FROM CTE
        WHERE DT < @EndDate
        )
    SELECT *
    FROM CTE