2012-11-08 53 views
0

我有一个保存工程师,appt_date和appt_slot的sql表。sql中的连续日期和约会

engineer_id, visit_date, visit_slot 

1,   20/10/12, All Day 
1,   21/10/12, AM 
2,   20/10/12, All Day 
2,   21/10/12, All Day 
2,   22/10/12, All Day 
3,   20/10/12, PM 
3,   21/10/12, All Day 
3,   22/10/12, PM 

我想什么来展示的是

Engineer_id, start_visit,  end_visit 

1,   20/10/12 All Day, 21/10/12 AM 
2,   20/10/12 All Day, 22/10/12 All Day 
3,   20/10/12 PM,  21/10/12 All Day 
3,   22/10/12 PM,  22/10/12 PM 

我与SQL显示在预定的休息挣扎,任何帮助,将不胜感激。 谢谢

+1

哪个RDBMS? SQL服务器?还是oracle? –

+0

到目前为止您有任何sql代码吗?如果是这样,张贴它 –

+0

不确定你的意思是“预订中断”?除了为每个engineer_id获取'min(visit_date)'和'max(visit_date)',还有更多吗? –

回答

1

你想要做的是在数据中查找序列。通常情况下,这是一连串的日子。你的情况很难,因为你有这些插槽,这大概是半天。

解决方案通过将插槽转换为时间来工作。我早上6点,早上6点任意使用。为晚上。我使用cross join这样做,因为新行是为“所有天”约会创建的。

使用此数据结构,您可以使用SQL技巧来识别属于一起的插槽。这个想法是枚举每个工程师在日期时间的插槽。然后减去半天与日期时间的枚举值相加。当这些值合适时,这是一个常数。出现空白时会显示新值。

最后,按照engineer_id和组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 
+0

谢谢,这太棒了!我可以延长它吗,可能会有夜晚和夜间工作的情况,所以一些工程师可能会连续工作几天而不是几天。我如何合并? :) – user1801525

+0

其实,我的意思是将其添加到答案。您需要添加日历表,因为有些日子可能不是工作日(周末,节假日)。您没有在原始问题中指定此限制,但解决此问题的唯一方法是使用日历。为了处理工程师的不同时间,我建议将不同工程师的查询作为单独的查询来处理。然后尝试将它们合并为一个。 –

+0

谢谢,但我不太清楚你的意思,即使有银行帐户和周末,这些都不属于非工作日,他们可以分配工作。 – user1801525