2013-11-01 3 views
0

데이터 열이있는 테이블이있는 경우 항목 사이의 시간 간격을 어떻게 계산합니까? 1 행이 이전 행의 상태 변경을 효과적으로 의미한다고 가정합니다. 예SQL Server : 날짜 값 사이의 시간 계산

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 시간 밥 아웃 : 59.5 시간 밥 결석 1 시간 조 물 : 60.5 시간 조 아웃 : 59.5 시간 조 결석 1 시간

+0

'DateTime' 열에 의해 제공된 행의 순서가 맞습니까? 그렇지 않으면 _ 이전 행 _은별로 의미가 없습니다. – HABO

+0

팁 : 키워드가 아닌 다른 것을 사용하여 엔티티 이름을 지정할 수 있습니다. 'SELECT [DELETE] FROM [WHERE] [FROM] <[INSERT] ORDER BY [INT]'는 누구에게 혼동을 줄 수 있습니다. – HABO

+0

감사합니다. 물론 이것은 예제 테이블입니다. 엔티티의 이름이 적절합니다. – Fearghal

답변

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] 

주 행 번호.

또한 쿼리에서는 데이터 형식과 이름 및 상태 열의 실제 값에 대해 몇 가지 가정을했습니다. 일반적인 접근 방식은 동일하게 유지됩니다.

+0

환상적 -이 효과가 있습니다. 이제 실수로 중요한 세부 정보를 포함하는 것을 잊어 버렸습니다. 세 번째 열로 그룹화 할 수 있습니까? 내 원래의 질문을 편집했습니다 - 가능합니까? – Fearghal

+0

예. 이름을 전달하고 group by 절에 추가해야합니다. 나는 쿼리를 업데이트 할 것이다. –

+0

YUP - 알았어, 다시 한 번 환상적인 방법이다. – Fearghal