t-sql从查询中的更多行获取总小时数

v2g6jxz6  于 2021-07-29  发布在  Java
关注(0)|答案(1)|浏览(274)

如何从本例中获取总小时数:第2行中的时段不包含在结果中,第1行包含第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

查询:

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;


注:
有没有可能使用一些工具,我可以加载数据,并获得像我的图像示例这样的结果?

ej83mcc0

ej83mcc01#

这是一种缺口和孤岛问题。您可以使用累计值来确定每一行是否是连续时间段的开始 max() . 然后用一个累积的和来得到时间段的开始。最后是聚合。因此,对于各个时段:

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;

然后可以执行最终聚合:

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;

这是一把小提琴。

相关问题