Reputation: 13
Data
id date
2380 10/30/12 09:00:00
2380 10/30/12 09:05:00
2380 10/30/12 09:10:00
2380 10/30/12 09:15:00
2381 10/30/12 10:00:00
2381 10/30/12 10:05:00
2381 10/30/12 10:10:00
2381 10/30/12 10:15:00
2382 10/30/12 11:00:00
2382 10/30/12 11:05:00
2382 10/30/12 10:10:00
2382 10/30/12 10:15:00
and I want the following solution
id date duration
2380 10/30/12 09:00:00 00:00:00
2380 10/30/12 09:05:00 00:05:00
2380 10/30/12 09:10:00 00:10:00
2380 10/30/12 09:15:00 00:15:00
2381 10/30/12 10:00:00 00:00:00
2381 10/30/12 10:05:00 00:05:00
2381 10/30/12 10:10:00 00:10:00
2381 10/30/12 10:15:00 00:15:00
2382 10/30/12 11:00:00 00:00:00
2382 10/30/12 11:05:00 00:05:00
2382 10/30/12 10:10:00 00:10:00
2382 10/30/12 10:15:00 00:10:00
I have tried to understand the logic behind the following thread but it's difficult to understand.
Substract date from previous row by group (using R)
select id, date, date - (select min(date) from date group by id) as duration
from date
Closest I have got is for one id.
Upvotes: 0
Views: 80
Reputation: 5442
Try this below example hope this is what you are looking as output,
declare @t1 table
(
id int,
dtdate datetime
)
insert into @t1 values(2380,'10/30/12 09:00:00')
insert into @t1 values(2380,'10/30/12 09:05:00')
insert into @t1 values(2380,'10/30/12 09:10:00')
insert into @t1 values(2380,'10/30/12 09:15:00')
insert into @t1 values(2381,'10/30/12 10:00:00')
insert into @t1 values(2381,'10/30/12 10:05:00')
insert into @t1 values(2381,'10/30/12 10:10:00')
insert into @t1 values(2381,'10/30/12 10:15:00')
insert into @t1 values(2382,'10/30/12 11:00:00')
insert into @t1 values(2382,'10/30/12 11:05:00')
insert into @t1 values(2382,'10/30/12 10:10:00')
insert into @t1 values(2382,'10/30/12 10:15:00')
;WITH CTE AS (
SELECT
rownum = ROW_NUMBER() OVER (partition by id ORDER BY id,dtDate),
id,dtDate
FROM @t1 p
)
SELECT
a.id,
a.dtDate,
CASE WHEN prev.dtdate is NULL THEN '00:00:00' ELSE convert(nvarchar(8),a.dtdate- prev.dtdate,108) END as duration
FROM CTE a
LEFT JOIN CTE prev ON a.id = prev.id AND prev.rownum = a.rownum - 1
Upvotes: 3
Reputation: 3363
The key to my approach is to find the minimum date value for each id which I refer to as the ReferenceDate. Then I join the main table to that and do the date math with the DATEDIFF() function and transform the results to hh:mi:ss with the CONVERT() function using style 108. Here is the dbfiddle.
IF OBJECT_ID('tempdb.dbo.#MyTable', 'U') IS NOT NULL
DROP TABLE #MyTable;
CREATE TABLE #MyTable
(
id INTEGER NOT NULL
, date DATETIME NOT NULL
);
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:00:00');
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:05:00');
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:10:00');
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:15:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:00:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:05:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:10:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:15:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 11:00:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 11:05:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 10:10:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 10:15:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 12:15:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 10:15:30');
SELECT a.*
, CONVERT(NVARCHAR(8), a.date - b.ReferenceDate, 108) AS duration
FROM #MyTable AS a
INNER JOIN (
SELECT id, MIN(date) AS ReferenceDate
FROM #MyTable GROUP BY id) AS b ON a.id = b.id;
Upvotes: 0