简体   繁体   中英

T-SQL get sum hours from more row in query

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM