2013-11-01 73 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'列提供的行的順序?否則_previous row_沒有多大意義。 – HABO

+0

提示:您可能需要考慮使用非關鍵字命名實體。 'SELECT [DELETE] FROM [WHERE] 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 - 明白了,thx再次,這是一個奇妙的方法。 – Fearghal