显示每月出勤日期明智
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
查看实际查询。
我需要使用 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
查看实际查询。