2016-10-04 4 views
2

문제점이 있습니다. 2 차원을 기준으로 연속 날짜 범위 행을 병합하는 방법을 알 수 없습니다. 하나는 나를 위해 OK이지만, 두 번째는 문제 연속 된 날짜 범위를 병합하는 방법 Oracle

이의이 및 act_level = prev_level 연속 날짜 범위를 네 가지 가능한 시나리오

emp_id | level | date_from | date_to  
-------------------------------------------------- 
    1  | A  | 7/31/2015 | 3/31/2016 
    1  | A  | 4/1/2016 | 1/1/3000 

    2  | A  | 7/31/2015 | 1/1/3000 

    3  | A  | 5/31/2015 | 12/31/2015 
    3  | B  | 1/1/2016 | 3/31/2016 
    3  | A  | 4/1/2016 | 6/30/2016 
    3  | B  | 7/1/2016 | 1/1/3000 

    4  | A  | 5/31/2015 | 12/31/2015 
    4  | A  | 1/1/2016 | 6/30/2016 
    4  | B  | 7/1/2016 | 1/1/3000 

내가 만 행을 병합 할,와이 구조에 테이블을 가정 해 봅시다하게

나는이 나에게 거의 resu를주는이

SELECT emp_id 
, level 
, date_from 
, date_to 
-- 
, CASE 
    WHEN lag(level) over (partition by emp_id order by date_from) = level THEN 
     CASE 
      WHEN lag(date_to) over (partition by emp_id, level order by date_from) = date_from-1 
       THEN lag(date_from) over (partition by code_employee, level_name order by date_from) 
      ELSE NULL 
     END 
    ELSE 
     CASE 
      WHEN lag(level) over (partition by emp_id order by date_from) = level 
        OR 
        lead(level) over (partition by emp_id order by date_from) = level 
       THEN NULL 
      ELSE date_from 
     END 
    END date_from_new 
, date_to as date_to_new 
-- 
FROM src_table 
-- 
WHERE 1=1 

그런 짓을하려고 내가 원하는 LTS는 :

emp_id | level | date_from | date_to | d_from_new | d_from_to 
-------------------------------------------------------------------------- 
    1  | A  | 7/31/2015 | 3/31/2016 |   | 3/31/2016 
    1  | A  | 4/1/2016 | 1/1/3000 | 7/31/2015 | 1/1/3000 

    2  | A  | 7/31/2015 | 1/1/3000 | 7/31/2015 | 1/1/3000 

    3  | A  | 5/31/2015 | 12/31/2015 | 5/31/2015 | 12/31/2015 
    3  | B  | 1/1/2016 | 3/31/2016 | 1/1/2016 | 3/31/2016 
    3  | A  | 4/1/2016 | 6/30/2016 | 4/1/2016 | 6/30/2016 
    3  | B  | 7/1/2016 | 1/1/3000 | 7/1/2016 | 1/1/3000 

    4  | A  | 5/31/2015 | 12/31/2015 |   | 12/31/2015 
    4  | A  | 1/1/2016 | 6/30/2016 | 5/31/2015 | 6/30/2016 
    4  | B  | 7/1/2016 | 1/1/3000 | 7/1/2016 | 1/1/3000 

난 그냥 d_from_new (date_from_new)하지 null 값에 대한 결과를 필터링합니다. 그러나 예를 들어 연속 된 날짜 범위 또는 8 배의 동일한 수준에 3 배가있을 경우 어떤 일이 발생할지 확실하지 않습니다.

솔직히 - 나는 쿼리 :

당신은 어떤 "perfomence 친화적 인"과 "눈 친화적"솔루션이 있습니까 좋아하지 않아?

select emp_id, lvl, min(date_from) df, max(date_to) dt 
    from (
    select s2.*, rn - sum(marker) over (order by rn) as grp 
     from (
     select s1.*, 
       row_number() over (order by emp_id, date_from) rn, 
       case when lag(lvl) over (partition by emp_id order by date_from) 
         = lvl 
        and lag(date_to) over (partition by emp_id order by date_from) + 1 
         = date_from 
        then 1 
        else 0 
       end marker 
      from src_table s1) s2) 
    group by emp_id, lvl, grp 
    order by emp_id, min(date_from) 

첫 번째 하위 쿼리 S1에서 나는 마커 추가, 이전 레벨이 해당되며, 날짜가 연속 경우 (1)가 할당됩니다

+0

하지 act_level = prev_level''뒤에 있지만, [간격 포장]을 살펴해야 어떤 논리 확인 (http://blogs.solidq.com/en/ szserver/packing-intervals /)를 참조하십시오. SQL Server 용으로 작성되었지만 Oracle은 여기에서 사용되는 모든 분석 기능을 지원합니다. –

답변

0

이 쿼리를 시도하십시오. 두 번째 하위 쿼리에서이 마커는 일치하는 모든 행에 대해 동일한 값을 갖는 GRP 열을 작성하는 데 사용됩니다. 이 열은 최종 그룹화 쿼리에 사용되어 최소 date_from 및 최대 date_to을 찾습니다. 내부 쿼리를 개별적으로 실행하여 각 단계에서 어떤 일이 발생하는지 확인하십시오. 세 개 이상의 연속 된 행이 있는지 테스트합니다.

테스트 데이터 및 출력 :

create table src_table (emp_id number(6), lvl varchar2(2), date_from date, date_to date); 
insert into src_table values (1, 'A', date '2015-07-31', date '2016-03-31'); 
insert into src_table values (1, 'A', date '2016-04-01', date '3000-01-01'); 
insert into src_table values (2, 'A', date '2015-07-31', date '3000-01-01'); 
insert into src_table values (3, 'A', date '2015-05-31', date '2015-12-31'); 
insert into src_table values (3, 'B', date '2016-01-01', date '2016-03-31'); 
insert into src_table values (3, 'A', date '2016-04-01', date '2016-06-30'); 
insert into src_table values (3, 'B', date '2016-07-01', date '3000-01-01'); 
insert into src_table values (4, 'A', date '2015-05-31', date '2015-12-31'); 
insert into src_table values (4, 'A', date '2016-01-01', date '2016-06-30'); 
insert into src_table values (4, 'B', date '2016-07-01', date '3000-01-01'); 

EMP_ID LVL DF   DT 
------- --- ----------- ----------- 
     1 A 2015-07-31 3000-01-01 
     2 A 2015-07-31 3000-01-01 
     3 A 2015-05-31 2015-12-31 
     3 B 2016-01-01 2016-03-31 
     3 A 2016-04-01 2016-06-30 
     3 B 2016-07-01 3000-01-01 
     4 A 2015-05-31 2016-06-30 
     4 B 2016-07-01 3000-01-01 

8 rows selected 
관련 문제