2012-11-08 3 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 

내가 예약에서 휴식을 표시하는 SQL과 사투를 벌인거야

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 

이다, 어떤 도움을 크게 감상 할 수있다. 감사합니다.

+1

어느 RDBMS? SQL 서버? oracle? –

+0

지금까지 sql 코드가 있습니까? 그렇다면 –

+0

게시 하시겠습니까? "예약 중단"이란 무엇을 의미하는지 확신 할 수 없습니까? engineer_id마다'min (visit_date)'와'max (visit_date)'를 얻는 것 이상의 것이 있습니까? –

답변

1

원하는 것은 데이터에서 시퀀스를 찾는 것입니다. 일반적으로 이것은 일련의 일입니다. 이 슬롯을 가지고 있기 때문에 사건이 더 힘들어집니다.이 슬롯은 아마도 반나절 일 것입니다.

이 솔루션은 슬롯을 여러 번 변환하여 작동합니다. 나는 아침 6시와 오후 6시를 임의로 사용하고 있습니다. 저녁. "All Days"약속에 대해 새 행이 만들어지기 때문에 cross join을 사용하여이 작업을 수행합니다.

이 데이터 구조를 사용하면 SQL 트릭을 사용하여 함께 속한 슬롯을 식별 할 수 있습니다. 아이디어는 datetime에 의해 각 엔지니어에 대한 슬롯을 열거하는 것입니다. 그런 다음 반나절을 뺀 후 datetime에서 열거 된 값을 뺍니다. 값이 순서에있을 때 이것은 상수입니다. 간격이 있으면 새 값이 나타납니다.

마지막으로 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