2012-01-23 2 views
1

시간표에 등록한 공휴일을 생성하는 쿼리가 있습니다. 시간표의 각 요일은 별도의 기록이지만 휴가 (2011 년 12 월 26 일부터 2011 년 12 월 30 일)까지 1 주일 걸리면 쿼리로 한 블록 (1 행)으로 표시해야합니다. 는 대신연속 된 값을 가진 결과 집합 행 축소하기

: 지금 얻을 출력 여기

SELECT -1 ord_li_pers_plan_id 
     ,ts.person_id person_id 
     ,-1 order_line_id 
     ,ts.timesheet_dt start_dt 
     ,ts.timesheet_dt end_dt 
     ,'Vacation' project 
     ,null color 
     ,1013011 planning_type 
FROM timesheets ts 
    JOIN persons pers ON ts.person_id = pers.person_id 
    JOIN person_holidays per_hol ON 
    ts.person_holiday_id = per_hol.person_holiday_id 
    JOIN v_holiday_types hoty_peho ON 
    per_hol.holiday_type_id = hoty_peho.holiday_type_id 
WHERE ts.person_holiday_id IS NOT NULL 
AND per_hol.holiday_type_id IN (SELECT holiday_type_id FROM v_holiday_types) 
AND ts.person_id = :p_person_id 

그리고있다 :

-1 11182 -1 30-DEC-11 30-DEC-11 Vacation 1013011 
-1 11182 -1 29-DEC-11 29-DEC-11 Vacation 1013011 
-1 11182 -1 28-DEC-11 28-DEC-11 Vacation 1013011 
-1 11182 -1 27-DEC-11 27-DEC-11 Vacation 1013011 
-1 11182 -1 26-DEC-11 26-DEC-11 Vacation 1013011 
-1 11182 -1 31-OCT-11 31-OCT-11 Vacation 1013011 
-1 11182 -1 02-SEP-11 02-SEP-11 Vacation 1013011 
-1 11182 -1 29-JUL-11 29-JUL-11 Vacation 1013011 
-1 11182 -1 22-JUL-11 22-JUL-11 Vacation 1013011 
-1 11182 -1 25-APR-11 25-APR-11 Vacation 1013011 

UPDATE 여기

는 질문에 대한 약간의 단순화 된 내 쿼리입니다 쿼리는 다음을 출력해야합니다 :

-1 11182 -1 26-DEC-11 30-DEC-11 Vacation 1013011 
-1 11182 -1 31-OCT-11 31-OCT-11 Vacation 1013011 
-1 11182 -1 02-SEP-11 02-SEP-11 Vacation 1013011 
-1 11182 -1 29-JUL-11 29-JUL-11 Vacation 1013011 
-1 11182 -1 22-JUL-11 22-JUL-11 Vacation 1013011 
-1 11182 -1 25-APR-11 25-APR-11 Vacation 1013011 

첫 번째 행에 유의하십시오. 이제 전체 휴가를 나타냅니다.

업데이트 2

내 클라이언트는 다른 아이디어를 내놓았다. 이 쿼리는 사람이 할당 된 모든 프로젝트가있는 작업 표와 연결됩니다. 프로젝트 날짜는 원래 블록으로 저장되었습니다 (날짜 범위 당 1 레코드, 예 : 01/01/2012 - 10/01/2012 => 1 레코드). 이제 고객은 모든 날짜를 별도의 레코드로 저장하려고합니다. 그렇게하기가 어렵지 않습니다.

현재 문제는 ord_li_pers-plan_id가 PK이므로 그룹 by가 더 이상 작동하지 않는다는 것입니다.

첨부되어 있습니다. 다소 큰 것입니다.

SELECT person_id , 
    order_line_id , 
    MIN(start_dt) start_dt , 
    MAX(end_dt) end_dt , 
    project , 
    color , 
    planning_type, 
    ord_li_pers_plan_id 
    FROM 
    (SELECT ord_li_pers_plan_id , 
     person_id , 
     order_line_id , 
     start_dt , 
     end_dt , 
     project , 
     color , 
     planning_type , 
     SUM(gap) OVER (PARTITION BY person_id ORDER BY start_dt) contiguous_grp 
    FROM 
     (SELECT ord_li_pers_plan_id , 
     person_id , 
     order_line_id , 
     start_dt , 
     end_dt , 
     project , 
     color , 
     planning_type , 
     CASE 
      WHEN lag(end_dt) over(PARTITION BY person_id ORDER BY start_dt) + 1 >= start_dt 
      THEN 0 
      ELSE 1 
     END gap 
     FROM 
     (SELECT ord_li_pers_plan_id , 
      person_id , 
      order_line_id , 
      start_dt , 
      end_dt , 
      project , 
      color , 
      planning_type 
     FROM 
      (SELECT op.ord_li_pers_plan_id ord_li_pers_plan_id , 
      p.person_id person_id , 
      p.order_line_id order_line_id , 
      op.start_dt start_dt , 
      op.end_dt end_dt , 
      pl$planning.prep_tooltip(NVL2(ord.end_customer_id, end_cus.name, cus.name) 
      || ' - ' 
      || NVL2(ord_li.project_cd,ord_li.project_cd,ord.project_cd) 
      || ' - ' 
      || func_tp.name 
      || ' - ' 
      || ROUND((con_tp.contract_tp/5), 2) 
      ||' - ' 
      || bl$gen_codes.Name_by_Code_Id (op.planning_type)) project , 
      olc.color color , 
      op.planning_type planning_type 
      FROM order_line_person_planning op 
      JOIN order_line_persons p 
      ON p.ORDER_LINE_PERSON_ID = op.ORDER_LINE_PERSON_ID 
      JOIN order_lines ord_li 
      ON ord_li.order_line_id = p.order_line_id 
      JOIN orders ord 
      ON ord.order_id = ord_li.order_id 
      LEFT JOIN order_line_colors olc 
      ON olc.order_line_id = ord_li.order_line_id 
      JOIN customers cus 
      ON ord.customer_id=cus.customer_id 
      LEFT JOIN customers end_cus 
      ON ord.end_customer_id=end_cus.customer_id 
      LEFT JOIN v_contract_types con_tp 
      ON ord.contract_type_id=con_tp.contract_type_id 
      JOIN v_function_types func_tp 
      ON ord_li.function_id=func_tp.function_id 
      UNION 
      SELECT -1 ord_li_pers_plan_id , 
      ts.person_id person_id , 
      -1 order_line_id , 
      ts.timesheet_dt start_dt , 
      ts.timesheet_dt end_dt , 
      'Vacation' project , 
      '#99FF33' color , 
      -1 planning_type 
      FROM hrm_iadvise.timesheets ts 
      JOIN hrm_iadvise.persons pers 
      ON ts.person_id = pers.person_id 
      JOIN hrm_iadvise.person_holidays per_hol 
      ON ts.person_holiday_id = per_hol.person_holiday_id 
      JOIN hrm_iadvise.v_holiday_types hoty_peho 
      ON per_hol.holiday_type_id = hoty_peho.holiday_type_id 
      WHERE ts.person_holiday_id IS NOT NULL 
      UNION 
      SELECT -1 ord_li_pers_plan_id , 
      per_hol.person_id person_id , 
      -1 order_line_id , 
      hol.dt start_dt , 
      hol.dt end_dt , 
      'Vacation' project , 
      '#99FF33' color , 
      -1 planning_type 
      FROM holidays hol 
      JOIN person_holidays per_hol 
      ON per_hol.holiday_type_id = hol.holiday_type_id 
      JOIN countries coty 
      ON coty.country_id = hol.country_id 
      WHERE coty.country_cd = 150 
     ) 
     ) 
    ) 
    ) 
    GROUP BY person_id , 
    order_line_id , 
    project , 
    color , 
    planning_type , 
    contiguous_grp, 
    ord_li_pers_plan_id; 

첫 번째 쿼리는 한 사람이 두 번째 쿼리가 사람이 이미 세 번째 쿼리는 공휴일의 모든 를 얻을 수 등록한 모든 휴가를 얻을 수 에 할당 모든 프로젝트를 가져옵니다

미리 감사드립니다.

답변

1

이 작업을 수행하려면 계층 적 쿼리를 사용해야합니다. 다음과 같이 사용하십시오.

SELECT 
    person_id, 
    person_holiday_id, 
    MIN(BEGIN), 
    END 
FROM 
(
    SELECT 
     person_id, 
     person_holiday_id, 
     connect_by_root(timesheet_dt) AS BEGIN, 
     timesheet_dt AS END, 
     connect_by_isleaf AS is_leaf 
    FROM 
     timesheets 
     CONNECT BY 
      PRIOR TRUNC(timesheet_dt) + 1 = TRUNC(timesheet_dt) 
      AND PRIOR person_id = person_id 
) 
WHERE 
    is_leaf = 1 
GROUP BY 
    person_id, 
    person_holiday_id, 
    END 
; 

사용자 당 계속 휴가 기간당 하나의 행을 반환합니다. 이것을 뷰에 넣고 질문에 게시 한 쿼리의 timesheets 테이블 대신 사용하십시오.

참고 : timesheets의 모든 행이 계층 적 쿼리의 루트 행으로 그리고 아마도 잎 행 및 중간 행으로 사용되기 때문에

  1. 이 쿼리는 최고 성능을 필요가 없습니다. 하위 쿼리를 비교하고 전체 쿼리에서 반환하는 행 수와 반환하는 행 수를 비교할 때이를 확인할 수 있습니다.
  2. timesheet_dt에 색인을 넣고 시간 부분을 포함하지 않으면 성능을 향상시킬 수 있습니다. 그러면 TRUNC 기능을 제거 할 수 있습니다.
  3. 토요일과 일요일이 timesheets 테이블에 입력되지 않은 경우이 진술서의 최대 휴가 기간은 월요일에서 금요일까지 1 주입니다. 이것이 문제가되면 CONNECT BY 절을 조정해야합니다. 그러나 timesheets 테이블에 입력되지 않은 공휴일 문제는 해결되지 않습니다.
2

분석을 사용할 수 있습니다. 데이터는 한 번만 읽습니다.

SQL> WITH your_query AS (
    2  SELECT 11182 person_id, to_date('30-DEC-11') start_dt, 
    3   to_date('30-DEC-11') end_dt FROM dual 
    4 UNION ALL SELECT 11182,to_date('29-DEC-11'),to_date('29-DEC-11') FROM DUAL 
    5 UNION ALL SELECT 11182,to_date('28-DEC-11'),to_date('28-DEC-11') FROM DUAL 
    6 UNION ALL SELECT 11182,to_date('27-DEC-11'),to_date('27-DEC-11') FROM DUAL 
    7 UNION ALL SELECT 11182,to_date('26-DEC-11'),to_date('26-DEC-11') FROM DUAL 
    8 UNION ALL SELECT 11182,to_date('31-OCT-11'),to_date('31-OCT-11') FROM DUAL 
    9 UNION ALL SELECT 11182,to_date('02-SEP-11'),to_date('02-SEP-11') FROM DUAL 
10 UNION ALL SELECT 11182,to_date('29-JUL-11'),to_date('29-JUL-11') FROM DUAL 
11 UNION ALL SELECT 11182,to_date('22-JUL-11'),to_date('22-JUL-11') FROM DUAL 
12 UNION ALL SELECT 11182,to_date('25-APR-11'),to_date('25-APR-11') FROM DUAL 
13 ) 
14 SELECT person_id, MIN(start_dt) start_dt, MAX(end_dt) end_dt 
15 FROM (SELECT person_id, start_dt, end_dt, 
16     SUM(gap) over(PARTITION BY person_id 
17        ORDER BY start_dt) contiguous_grp 
18    FROM (SELECT person_id, start_dt, end_dt, 
19       CASE WHEN lag(end_dt) over(PARTITION BY person_id 
20          ORDER BY start_dt) + 1 >= start_dt 
21        THEN 0 ELSE 1 
22       END gap 
23      FROM (SELECT * FROM your_query))) 
24 GROUP BY person_id, contiguous_grp 
25 ORDER BY 1, 2 DESC; 
PERSON_ID START_DT END_DT 
---------- --------- --------- 
    11182 26-DEC-11 30-DEC-11 
    11182 31-OCT-11 31-OCT-11 
    11182 02-SEP-11 02-SEP-11 
    11182 29-JUL-11 29-JUL-11 
    11182 22-JUL-11 22-JUL-11 
    11182 25-APR-11 25-APR-11 
+0

안녕하세요 빈센트,이 사람이 해냈습니다. 빠른 답변을 보내 주셔서 감사합니다. –