显示每月出勤日期明智

Displaying Monthly Attendance Date Wise

我需要使用 PIVOT 以月格式显示出勤数据。但是想不通应该怎么做。

下面是我的table结构

出席人数:

AttendanceID    EmployeeID     AttendanceDateTime

员工:

EmployeeID     EmployeeName

假期:

HolidayID     HolidayDate

离开:

LeaveID    EmployeeID    LeaveDateTime    IsApproved

我想根据上面提供的数据显示如下结果table

EmployeeName    01-09-2016    02-09-2016    03-09-2016    04-09-2016
     A           Present        Absent        Holiday        Leave

因此,在创建日期轴心之前,您可能要做的第一件事就是确定要轴心的日期。出于示例的目的,我刚刚提供了一种方法,您可以在此答案中获取特定范围内的每个日期,但这实际上取决于您要查找的内容。

SELECT *
FROM (
    SELECT E.EmployeeID, E.EmployeeName, T.DateToCheck, COALESCE(H.val, A.val, L.val, 'Absent') val
    FROM tblEmployee E
    CROSS JOIN (
        SELECT CAST(DATEADD(DAY, number, '2016-09-01') AS DATE)
        FROM master..spt_values
        WHERE type = 'P'
        AND number <= 3) T(DateToCheck)
    LEFT JOIN (SELECT 'Holiday' val, HolidayDate FROM tblHoliday) H ON H.HolidayDate = T.DateToCheck
    LEFT JOIN (SELECT 'Present' val, AttendanceDateTime, EmployeeID FROM tblAttendance) A ON CAST(A.AttendanceDateTime AS DATE) = T.DateToCheck AND A.EmployeeID = E.EmployeeID
    LEFT JOIN (SELECT 'Leave' val, LeaveDateTime, EmployeeID FROM tblLeave) L ON CAST(L.LeaveDateTime AS DATE) = T.DateToCheck AND L.EmployeeID = E.EmployeeID) T
PIVOT (MAX(val) FOR DateToCheck IN ([2016-09-01], [2016-09-02], [2016-09-03], [2016-09-04])) P;

这里的基本逻辑是你想生成你的日期来检查,将这些日期与每个不同的表进行比较(使用左连接或外部应用),只得到一个结果(这个答案中的逻辑使用合并以决定它将显示哪个值),然后旋转结果。

编辑: 如果您需要 PIVOT 一组动态的列名(例如动态日期范围),您将需要使用 dynamic SQL。这是您可以做到的一种方法:

DECLARE @SQL VARCHAR(MAX) = '', @dateRange VARCHAR(MAX) = '', @startDate DATE = '2016-09-01', @endDate DATE = '2016-09-05';

SELECT @dateRange += ',' + QUOTENAME(DATEADD(DAY, number, @startDate))
FROM master..spt_values 
WHERE type = 'P'
AND DATEADD(DAY, number, @startDate) <= @endDate;

SELECT @dateRange = STUFF(@dateRange, 1, 1, '');

SELECT @SQL = 'SELECT *
FROM (
    SELECT E.EmployeeID, E.EmployeeName, T.DateToCheck, COALESCE(H.val, A.val, L.val, ''Absent'') val
    FROM tblEmployee E
    CROSS JOIN (
        SELECT CAST(DATEADD(DAY, number, ''' + CAST(@startDate AS CHAR(10)) + ''') AS DATE)
        FROM master..spt_values
        WHERE type = ''P''
        AND DATEADD(DAY, number, ''' + CAST(@startDate AS CHAR(10)) + ''') <= ''' + CAST(@endDate AS CHAR(10)) + ''') T(DateToCheck)
    LEFT JOIN (SELECT ''Holiday'' val, HolidayDate FROM tblHoliday) H ON H.HolidayDate = T.DateToCheck
    LEFT JOIN (SELECT ''Present'' val, AttendanceDateTime, EmployeeID FROM tblAttendance) A ON CAST(A.AttendanceDateTime AS DATE) = T.DateToCheck AND A.EmployeeID = E.EmployeeID
    LEFT JOIN (SELECT ''Leave'' val, LeaveDateTime, EmployeeID FROM tblLeave) L ON CAST(L.LeaveDateTime AS DATE) = T.DateToCheck AND L.EmployeeID = E.EmployeeID) T
PIVOT (MAX(val) FOR DateToCheck IN (' + @dateRange + ')) P;';

PRINT @SQL;
EXEC(@SQL);

更改开始日期和结束日期将更改输出。您可以使用 PRINT @SQL 查看实际查询。