您要做的是在数据中查找序列。通常,这是几天的序列。你的情况更难,因为你有这些插槽,大概是半天。
该解决方案通过将时隙转换为时间来工作。我随意使用早上 6:00 和晚上 6 点。我使用 a 来执行此操作cross join
,因为新行是为“全天”约会创建的。
使用此数据结构,您可以使用 SQL 技巧来识别属于一起的插槽。这个想法是按日期时间枚举每个工程师的插槽。然后从 datetime 中减去半天 tiems 的枚举值。当值有序时,这是一个常数。有间隙时会出现一个新值。
最后,按engineer_id和group id分组,得到你想要的数据。
以下查询显示了这一点。它将最终结果保留为日期时间,而不是将它们转换回插槽。
with t as (
select 1 as engineer_id, cast('2012-10-20' as date) as visit_date, 'All Day' as visit_slot union all
select 1 as engineer_id, cast('2012-10-21' as date) as visit_date, 'AM' as visit_slot union all
select 2 as engineer_id, cast('2012-10-20' as date) as visit_date, 'All Day' as visit_slot union all
select 2 as engineer_id, cast('2012-10-21' as date) as visit_date, 'All Day' as visit_slot union all
select 2 as engineer_id, cast('2012-10-22' as date) as visit_date, 'All Day' as visit_slot union all
select 3 as engineer_id, cast('2012-10-20' as date) as visit_date, 'PM' as visit_slot union all
select 3 as engineer_id, cast('2012-10-21' as date) as visit_date, 'All Day' as visit_slot union all
select 3 as engineer_id, cast('2012-10-22' as date) as visit_date, 'PM' as visit_slot
),
tslots as (
select t2.*
from (select t.engineer_id,
(CAST(visit_date as datetime) +
(case when t.visit_slot in ('All Day', const.slot) then const.hr/24.0 end)
) as visit_datetime
from t cross join
(select 'AM' as slot, 6 as hr union all select 'PM', 18) const
) t2
where visit_datetime is not null
group by engineer_id, visit_datetime
)
select engineer_id, MIN(visit_datetime) as min_datetime, MAX(visit_datetime) as max_datetime
from (select ts.*,
ROW_NUMBER() over (partition by engineer_id order by visit_datetime) as seqnum,
visit_datetime - 0.5*(ROW_NUMBER() over (partition by engineer_id order by visit_datetime)) as groupid
from tslots ts
) ts1
group by engineer_id, groupid
order by 1, 2