我有一个简单的桌子,可以全天存储员工的时钟输入和时钟输出:
╔══════════╦══════════════════╦════════════╗
║ Employee ║ PunchDateTime ║ ActionType ║
╠══════════╬══════════════════╬════════════╣
║ John ║ 2014/03/26 08:00 ║ IN ║
║ Mark ║ 2014/03/26 08:12 ║ IN ║
║ John ║ 2014/03/26 08:50 ║ OUT ║
║ John ║ 2014/03/26 09:29 ║ IN ║
║ Mark ║ 2014/03/26 10:35 ║ OUT ║
║ John ║ 2014/03/26 10:55 ║ OUT ║
║ Mark ║ 2014/03/26 11:42 ║ IN ║
║ John ║ 2014/03/26 12:38 ║ IN ║
║ John ║ 2014/03/26 16:21 ║ OUT ║
║ Mark ║ 2014/03/26 16:49 ║ OUT ║
╚══════════╩══════════════════╩════════════╝
我想构建一个计算进出时间的查询。最终结果应如下所示:
╔══════════╦══════════════════╦════════════╦════════╦═════════╗
║ Employee ║ PunchDateTime ║ ActionType ║ TimeIn ║ TimeOut ║
╠══════════╬══════════════════╬════════════╬════════╬═════════╣
║ John ║ 2014/03/26 08:00 ║ IN ║ - ║ - ║
║ Mark ║ 2014/03/26 08:12 ║ IN ║ - ║ - ║
║ John ║ 2014/03/26 08:50 ║ OUT ║ 00:40 ║ - ║
║ John ║ 2014/03/26 09:29 ║ IN ║ - ║ 00:39 ║
║ Mark ║ 2014/03/26 10:35 ║ OUT ║ 02:23 ║ - ║
║ John ║ 2014/03/26 10:55 ║ OUT ║ 01:26 ║ - ║
║ Mark ║ 2014/03/26 11:42 ║ IN ║ - ║ 01:07 ║
║ John ║ 2014/03/26 12:05 ║ IN ║ - ║ 01:10 ║
║ John ║ 2014/03/26 16:21 ║ OUT ║ 04:16 ║ - ║
║ Mark ║ 2014/03/26 16:49 ║ OUT ║ 05:07 ║ - ║
╚══════════╩══════════════════╩════════════╩════════╩═════════╝
标准:
如何计算TimeIn和TimeOut(对于一名员工)的图形表示:
答案 0 :(得分:3)
你去:
if object_id('tempdb..#Punch') is not null
drop table #Punch
create table #Punch(
Employee varchar(50) not null,
PunchDateTime datetime not null,
ActionType varchar(3) not null
)
insert into #Punch select 'John', '2014/03/26 06:00', 'OUT' -- extra "out"
insert into #Punch select 'John', '2014/03/26 08:00', 'IN'
insert into #Punch select 'John', '2014/03/26 08:01', 'IN' -- extra "in"
insert into #Punch select 'John', '2014/03/26 08:02', 'IN' -- extra "in"
insert into #Punch select 'John', '2014/03/26 08:03', 'IN' -- extra "in"
insert into #Punch select 'Mark', '2014/03/26 08:12', 'IN'
insert into #Punch select 'John', '2014/03/26 08:50', 'OUT'
insert into #Punch select 'John', '2014/03/26 08:51', 'OUT' -- extra "out"
insert into #Punch select 'John', '2014/03/26 08:52', 'OUT' -- extra "out"
insert into #Punch select 'John', '2014/03/26 08:53', 'OUT' -- extra "out"
insert into #Punch select 'John', '2014/03/26 09:29', 'IN'
insert into #Punch select 'Mark', '2014/03/26 10:35', 'OUT'
insert into #Punch select 'John', '2014/03/26 10:55', 'OUT'
insert into #Punch select 'Mark', '2014/03/26 11:42', 'IN'
insert into #Punch select 'John', '2014/03/26 12:38', 'IN'
insert into #Punch select 'John', '2014/03/26 16:21', 'OUT'
insert into #Punch select 'Mark', '2014/03/26 16:49', 'OUT'
select *
from (
select
p.Employee,
p.PunchDateTime,
p.ActionType,
case when p.ActionType = 'IN'
then '-'
else coalesce(substring(convert(varchar(30), p.PunchDateTime - p.PreviousPunchDateTime, 20), 12, 5), '-')
end as TimeIn,
case when p.ActionType = 'OUT'
then '-'
else coalesce(substring(convert(varchar(30), p.PunchDateTime - p.PreviousPunchDateTime, 20), 12, 5), '-')
end as TimeOut
from (
select
a.Employee,
a.PunchDateTime,
a.ActionType,
(
select top 1 b.PunchDateTime
from #Punch b
where b.Employee = a.Employee
and b.PunchDateTime < a.PunchDateTime
and b.ActionType <> a.ActionType
and datediff(day, b.PunchDateTime, a.PunchDateTime) = 0 -- same day
and not exists(
select 1
from #Punch c
where c.Employee = a.Employee
and c.ActionType = a.ActionType
and c.PunchDateTime < a.PunchDateTime
and c.PunchDateTime > b.PunchDateTime
)
and not (
b.ActionType = 'OUT'
and not exists(select 1 from #Punch d where d.Employee = a.Employee and d.ActionType = 'IN' and d.PunchDateTime < b.PunchDateTime)
)
order by b.PunchDateTime asc
) as PreviousPunchDateTime
from #Punch a
) p
) p2
where not (p2.ActionType = 'OUT' and p2.TimeIn = '-' and p2.TimeOut = '-')
and not (
p2.ActionType = 'IN' and p2.TimeIn = '-' and p2.TimeOut = '-'
and exists(select 1 from #Punch a where a.ActionType = 'IN' and a.Employee = p2.Employee and a.PunchDateTime < p2.PunchDateTime))
order by
p2.PunchDateTime