How get sum hours from this example: Period in row 2 not include in resault, row 1 contains time from row 2.
Order Name Start Finish
1. Marc 01/01/2020 10:00 01/01/2020 11:00
2. Marc 01/01/2020 10:15 01/01/2020 11:00
3. Marc 01/01/2020 12:00 01/01/2020 14:00
Query:
with cte as (
Select 'Marc' as name, '2020-01-01 10:00:00.000' as start,'2020-01-01 11:00:00.000' as finish
union all
Select 'Marc' as name, '2020-01-01 10:15:00.000' as start,'2020-01-01 11:00:00.000' as finish
union all
Select 'Marc' as name, '2020-01-01 12:10:00.000' as start,'2020-01-01 14:00:00.000' as finish
)
select name, min(start) as start, max(finish) as finish
from (select t.*,
sum(case when prev_finish >= start then 0 else 1 end) over (partition by name order by start) as grp
from (select t.*,
max(finish) over (partition by name order by start rows between unbounded preceding and 1 preceding) as prev_finish
from cte
) t
) t
group by name, grp
)
select name, sum(datediff(hour, start, finish)) as hours
from t
group by name;
note:
Is it possible use some tool where I can load data and get resault like this my image example?
This is a type of gaps-and-islands problem. You can determine if each row is the start of a contiguous time period using a cumulative max()
. Then a cumulative sum to get the starts of the time periods. . . and finally aggregation. So, for the individual time periods:
select name, min(start) as start, max(finish) as finish
from (select t.*,
sum(case when prev_finish >= start then 0 else 1 end) over (partition by name order by start) as grp
from (select t.*,
max(finish) over (partition by name order by start rows between unbounded preceding and 1 preceding) as prev_finish
from t
) t
) t
group by name, grp;
You can then do the final aggregation:
with cte as (
Select 'Marc' as name, '2020-01-01 10:00:00.000' as start,'2020-01-01 11:00:00.000' as finish
union all
Select 'Marc' as name, '2020-01-01 10:15:00.000' as start,'2020-01-01 11:00:00.000' as finish
union all
Select 'Marc' as name, '2020-01-01 12:10:00.000' as start,'2020-01-01 14:00:00.000' as finish
),
t as (
select name, min(start) as start, max(finish) as finish
from (select t.*,
sum(case when prev_finish >= start then 0 else 1 end) over (partition by name order by start) as grp
from (select t.*,
max(finish) over (partition by name order by start rows between unbounded preceding and 1 preceding) as prev_finish
from cte t
) t
) t
group by name, grp
)
select name, sum(datediff(hour, start, finish)) as hours
from t
group by name;
Here is a db<>fiddle.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.