Reputation: 830
I have a table tbl
with the following sample code:
declare @tbl table
(
Date1 datetime,
Date2 datetime
)
insert into @tbl
values
('2020-06-03 11:00','2020-06-03 14:00'),
('2020-06-03 19:00','2020-06-04 01:00'),
('2020-06-04 11:00','2020-06-04 14:00')
select * from @tbl
I want to output the number of hours that where spent between the two columns.
Sample desired output:
Day | Hours
2020-06-03 | 8
2020-06-04 | 4
I tried doing:
select sum(datediff(hour,Date1,Date2)) from @tbl
group by cast(Date1 as date)
But this doesn't have in mind the interval that crossed the two days, outputting 9 and 3.
Any ideas on this?
Thanks!
Upvotes: 0
Views: 44
Reputation: 1270793
For the generic solution, you can use a recursive CTE to split the time spans into separate days and then aggregate:
with cte as (
select date1, date1 as date2,
date2 as enddate, 1 as lev
from t
union all
select date2,
(case when datediff(day, date1, enddate) = 0 then enddate
else dateadd(day, 1, datefromparts(year(date1), month(date1), day(date1)))
end) as date2,
enddate, 1 + lev
from cte
where date1 < enddate
)
select convert(date, date1), sum(datediff(hour, date1, date2))
from cte
group by convert(date, date1);
Here is a db<>fiddle.
Upvotes: 1
Reputation: 95950
I'm ripping this answer from another, with a slight difference to aggregate per day instead.
You need to split your values into each day, and then you can SUM
per day:
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP(SELECT MAX(DATEDIFF(DAY, Date1, Date2)+1) FROM @tbl)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3), --1000 days enough?
Dates AS(
SELECT DATEADD(DAY, T.I,CONVERT(date,YT.Date1)) AS [Date],
CASE WHEN T.I = 0 THEN YT.Date1 ELSE DATEADD(DAY, T.I,CONVERT(date,YT.Date1)) END AS StartingDateTime,
CASE WHEN LEAD(T.I) OVER (PARTITION BY YT.Date1 ORDER BY T.I) IS NULL THEN YT.Date2 ELSE DATEADD(DAY, T.I+1,CONVERT(date,YT.Date1)) END AS EndingDateTime
FROM Tally T
JOIN @tbl YT ON T.I <= DATEDIFF(DAY, YT.Date1, YT.Date2))
SELECT D.[Date],
SUM(DATEDIFF(HOUR,D.StartingDateTime,D.EndingDateTime)) AS [Hours]
FROM Dates D
GROUP BY D.[Date];
Upvotes: 0