如果我有一个包含数据列的表,我如何计算条目之间的小时数。 假设1行有效地表示前一行的状态变化。 例如
TableA
Name Status(Int) DateTime (DateTiem2)
Bob In '2012-11-22 00:00:00'
Bob Out '2012-11-23 00:00:00'
Bob In '2012-11-24 00:00:00'
Bob Out '2012-11-25 00:00:00'
Bob In '2012-11-26 00:00:00'
Bob Out '2012-11-26 12:30:00'
Bob Absent '2012-11-27 00:00:00'
Bob In '2012-11-27 01:00:00
Jo In '2012-11-22 00:00:00'
Jo Out '2012-11-23 00:00:00'
Jo In '2012-11-24 00:00:00'
Jo Out '2012-11-25 00:00:00'
Jo In '2012-11-26 00:00:00'
Jo Out '2012-11-26 12:30:00'
Jo Absent '2012-11-27 00:00:00'
Jo In '2012-11-27 01:00:00
总计查询结果来自 鲍勃在:60.5小时 Bob Out:59.5小时 Bob Absent:1小时 Jo In:60.5小时 乔出:59.5小时 Jo Absent:1小时
答案 0 :(得分:1)
将表连接到自身,以便每一行按顺序匹配下一行。然后按分钟减去日期时间量(因为您需要小数小时)并将分钟除以60:
declare @T table
(
name varchar(20),
[status] int,
[DateTime] datetime2
)
insert into @T (name, [status], [DateTime])
values ('Bob', 0, '2012-11-22 00:00:00'),
('Bob', 1, '2012-11-23 00:00:00'),
('Bob', 0, '2012-11-24 00:00:00'),
('Bob', 1, '2012-11-25 00:00:00'),
('Bob', 0, '2012-11-26 00:00:00'),
('Bob', 1, '2012-11-26 12:30:00'),
('Bob', 2, '2012-11-27 00:00:00'),
('Bob', 1, '2012-11-27 01:00:00'),
('Jo', 0, '2012-11-22 00:00:00'),
('Jo', 1, '2012-11-23 00:00:00'),
('Jo', 0, '2012-11-24 00:00:00'),
('Jo', 1, '2012-11-25 00:00:00'),
('Jo', 0, '2012-11-26 00:00:00'),
('Jo', 1, '2012-11-26 12:30:00'),
('Jo', 2, '2012-11-27 00:00:00'),
('Jo', 1, '2012-11-27 01:00:00')
;with RowNumbers (RowNum, name, [status], [DateTime])
as
(
select
ROW_NUMBER() over (partition by name order by [DateTime]),
name,
[status],
[DateTime]
from @T
)
select
T1.name,
case T1.[status]
when 0 then 'In'
when 1 then 'Out'
when 2 then 'Absent'
end as [status],
sum(datediff(MINUTE, T1.[DateTime], T2.[DateTime]) / 60.0) as [hours]
from RowNumbers T1
inner join RowNumbers T2
on T1.RowNum = T2.RowNum - 1 -- joins the current row to the next one
and T1.name = T2.name
group by T1.name, T1.[status]
order by T1.Name, T1.[status]
请注意,上面的查询可能不会像在行号上有索引的派生表那样执行。
此外,查询我对名称和状态列的数据类型和实际值做了一些假设。一般方法保持不变。