SQL Server:计算日期值之间的时间

时间:2013-11-01 13:30:42

标签: sql-server-2008 datetime sum

如果我有一个包含数据列的表,我如何计算条目之间的小时数。 假设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小时

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]

请注意,上面的查询可能不会像在行号上有索引的派生表那样执行。

此外,查询我对名称和状态列的数据类型和实际值做了一些假设。一般方法保持不变。