[英]SQL Query for Attendance Matrix in SQL Server 2008 R2
I would like to generate one matrix attendance report based on employee entry_in and entry_out, both are datetime fields and group by date. 我想基于雇员的entry_in和entry_out生成一个矩阵出勤报告,它们都是日期时间字段和按日期分组。
generally I would like to calculate like this 通常我想这样计算
Please find the attachment 请找到附件
Please help me on this 请帮我
Here is a bit of a hack and slash, basically use RECURSIVE CTE
to get the time groups, then PIVOT
to generate the output you are after. 这有点小巧,基本上是使用RECURSIVE CTE
来获取时间组,然后使用PIVOT
来生成您想要的输出。
;WITH cte (groupNo, StartTime, EndTime)
AS (
SELECT CAST(1 AS INT) as groupNo, CAST('06:00' AS TIME) AS StartTime, CAST('07:00' AS TIME) AS EndTime
UNION ALL
SELECT groupNo + 1 AS groupNo, DATEADD(HOUR, 1, StartTime) AS StartTime, DATEADD(HOUR, 1, EndTime) AS EndTime
FROM cte
WHERE groupNo <= 13
)
SELECT emp_id, date_in, date_out,
COUNT(DISTINCT datetime_in) AS [NumberOfLogins],
SUM(ISNULL([1],0) + ISNULL([2],0) + ISNULL([3],0) + ISNULL([4],0) + ISNULL([5],0) + ISNULL([6],0) + ISNULL([7],0) + ISNULL([8],0) + ISNULL([9],0) + ISNULL([10],0) + ISNULL([11],0) + ISNULL([12],0) + ISNULL([13],0)) [Minutes],
SUM([1]) [6AM to 7AM],
SUM([2]) [7AM to 8AM],
SUM([3]) [8AM to 9AM],
SUM([4]) [9AM to 100AM],
SUM([5]) [10AM to 11AM],
SUM([6]) [11AM to 12PM],
SUM([7]) [12PM to 1PM],
SUM([8]) [1PM to 2PM],
SUM([9]) [2PM to 3PM],
SUM([10]) [3PM to 4PM],
SUM([11]) [4PM to 5PM],
SUM([12]) [5PM to 6PM],
SUM([13]) [6PM to 7PM]
FROM
(
SELECT emp_id, date_in AS datetime_in, CAST(date_in AS DATE) AS date_in, CAST(date_out AS DATE) AS date_out, cte.groupNo,
DATEDIFF(MINUTE, (CASE WHEN CAST(t.date_in AS TIME) > cte.StartTime THEN CAST(t.date_in AS TIME) ELSE cte.StartTime END),
(CASE WHEN cte.EndTime > CAST(t.date_out AS TIME) THEN CAST(t.date_out AS TIME) ELSE cte.EndTime END)) AS [minutes]
FROM scan_station_master t
INNER JOIN cte ON (cte.StartTime BETWEEN CAST(t.date_in as time) AND CAST(t.date_out AS TIME))
OR (cte.EndTime BETWEEN CAST(t.date_in AS TIME) AND CAST(t.date_out as time))
OR (CAST(t.date_in as time) >= cte.StartTime AND CAST(t.date_out as time) <= cte.EndTime)
) d
PIVOT
(
MAX([minutes])
FOR groupNo in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13])
) piv
GROUP BY emp_id, date_in, date_out
review and try with other sample data.will discuss t'row 查看并尝试其他示例数据。将讨论行
declare @t table(emp_id bigint,date_in datetime,date_out datetime)
insert into @t values
(392510,'2017/2/16 9:47','2017/2/16 11:31'),
(392510,'2017/2/17 11:26','2017/2/17 11:58')
,(392510,'2017/2/17 2:11 PM','2017/2/17 4:13 PM')
,(392510,'2017/2/18 15:30','2017/2/18 17:09')
,(392510,'2017/2/22 9:38 AM','2017/2/22 9:48 AM')
,(392510,'2017/2/22 11:55 AM','2017/2/22 12:10 PM')
,(392510,'2017/2/25 8:20 AM','2017/2/25 8:24 AM')
,(392510,'2017/2/26 13:37','2017/2/26 13:55')
;with CTE as
(
select t.emp_id
,t.date_in
,t.date_out
,case
when cast(date_in as time)>cast('7:00 AM' as time) and cast(date_in as time)>cast('6:00 AM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('7:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('7:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('7:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('7:00 AM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('7:00 AM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('7:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast('6:00 AM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('6:00 AM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[6 AM to 7 AM]
,case
when cast(date_in as time)>cast('8:00 AM' as time) and cast(date_in as time)>cast('7:00 AM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('8:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('8:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('8:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('8:00 AM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('8:00 AM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('8:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast('7:00 AM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('7:00 AM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[7 AM to 8 AM]
,case
when cast(date_in as time)>cast('9:00 AM' as time) and cast(date_in as time)>cast('8:00 AM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('9:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('9:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('9:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('9:00 AM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('9:00 AM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('9:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast('8:00 AM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('8:00 AM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[8 AM to 9 AM]
,case
when cast(date_in as time)>cast('10:00 AM' as time) and cast(date_in as time)>cast('9:00 AM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('10:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('10:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('10:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('10:00 AM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('10:00 AM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('10:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast('9:00 AM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('9:00 AM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[9 AM to 10 AM]
,case
when cast(date_in as time)>cast('11:00 AM' as time) and cast(date_in as time)>cast('10:00 AM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('11:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('11:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('11:00 AM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('11:00 AM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('11:00 AM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('11:00 AM' as time)) between 0 and 60
then datediff(MINUTE, cast('10:00 AM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('10:00 AM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[10 AM to 11 AM]
,case
when cast(date_in as time)>cast('12:00 PM' as time) and cast(date_in as time)>cast('11:00 AM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('12:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('12:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('12:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('12:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('12:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('12:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('11:00 AM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('11:00 AM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[11 AM to 12 PM]
,case
when cast(date_in as time)>cast('1:00 PM' as time) and cast(date_in as time)>cast('12:00 PM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('1:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('1:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('1:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('1:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('1:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('1:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('12:00 PM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('12:00 PM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[12 PM to 1 PM]
,case
when cast(date_in as time)>cast('2:00 PM' as time) and cast(date_in as time)>cast('1:00 PM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('2:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('2:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('2:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('2:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('2:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('2:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('1:00 PM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('1:00 PM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[1 PM to 2 PM]
,case
when cast(date_in as time)>cast('3:00 PM' as time) and cast(date_in as time)>cast('2:00 PM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('3:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('3:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('3:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('3:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('3:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('3:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('2:00 PM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('2:00 PM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[2 PM to 3 PM]
,case
when cast(date_in as time)>cast('4:00 PM' as time) and cast(date_in as time)>cast('3:00 PM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('4:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('4:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('4:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('4:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('4:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('4:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('3:00 PM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('3:00 PM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[3 PM to 4 PM]
,case
when cast(date_in as time)>cast('5:00 PM' as time) and cast(date_in as time)>cast('4:00 PM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('5:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('5:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('5:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('5:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('5:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('5:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('4:00 PM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('4:00 PM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[4 PM to 5 PM]
,case
when cast(date_in as time)>cast('6:00 PM' as time) and cast(date_in as time)>cast('5:00 PM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('6:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('6:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('6:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('6:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('6:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('6:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('5:00 PM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('5:00 PM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[5 PM to 6 PM]
,case
when cast(date_in as time)>cast('7:00 PM' as time) and cast(date_in as time)>cast('6:00 PM' as time) then null
when datediff(MINUTE, cast(date_in as time) ,cast('7:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('7:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast(date_in as time) ,cast(date_out as time))
when datediff(MINUTE, cast(date_in as time) ,cast('7:00 PM' as time)) <60
and datediff(MINUTE, cast(date_out as time) ,cast('7:00 PM' as time)) <0
then datediff(MINUTE, cast(date_in as time) ,cast('7:00 PM' as time))
when datediff(MINUTE, cast(date_out as time) ,cast('7:00 PM' as time)) between 0 and 60
then datediff(MINUTE, cast('6:00 PM' as time),cast(date_out as time) )
when datediff(MINUTE, cast('6:00 PM' as time) ,cast(date_out as time))>=60
then 60
else
null
end
[6 PM to 7 PM]
From @t t
)
select emp_id,min(date_in)date_in,max(date_out)date_out
,count(*)[Number of Login]
,sum([6 AM to 7 AM])[6 AM to 7 AM]
,sum([7 AM to 8 AM])[7 AM to 8 AM]
,sum([8 AM to 9 AM])[8 AM to 9 AM]
,sum([9 AM to 10 AM])[9 AM to 10 AM]
,sum([10 AM to 11 AM])[10 AM to 11 AM]
,sum([10 AM to 11 AM])[10 AM to 11 AM]
,sum([11 AM to 12 PM])[11 AM to 12 PM]
,sum([12 PM to 1 PM] )[12 PM to 1 PM]
,sum([1 PM to 2 PM])[1 PM to 2 PM]
,sum([2 PM to 3 PM])[2 PM to 3 PM]
,sum([3 PM to 4 PM])[3 PM to 4 PM]
,sum([4 PM to 5 PM])[4 PM to 5 PM]
,sum([5 PM to 6 PM])[5 PM to 6 PM]
,sum([6 PM to 7 PM])[6 PM to 7 PM]
from CTE t
group by t.emp_id,cast(date_in as date)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.