2012-01-23 10 views
1

私は、自分のタイムシートに人が登録した休日を生成するクエリを持っています。 タイムシートの毎日は別の記録ですが、休暇を取った場合(2011年12月26日から2011年12月30日まで)、これはクエリによって1ブロック(1行)で表されなければなりません。ここで連続した値を持つ結果セット行を折りたたむ

は私のクエリは、質問のために少し単純化している:

-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:

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 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 

最初の行に注意してください。今は休暇全体を表しています。

UPDATE 2

私のクライアントは、別のアイデアを思い付きました。このクエリは、人が割り当てられているすべてのプロジェクトを含むタイムシートにリンクされています。プロジェクトの日付は、もともとブロックとして保存されていました(日付範囲ごとに1レコード、例:01/01/2012 - 10/01/2012 => 1レコード)。クライアントは、すべての日付を別々のレコードとして保存したいと考えています。それはやりにくく、うまくいきます。

私が直面している問題は、ord_li_pers-plan_idがPKであるため、group 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; 

最初のクエリでは、人は2番目のクエリは、人はすでに第三クエリが祝日のすべてを取得します 登録されているすべての休日を取得します に割り当てられているすべてのプロジェクトを取得します

ありがとうございます

答えて

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 
; 

ユーザーあたり継続的な休暇期間ごとに1行を返します。これをビューに入れて、質問に投稿したクエリのtimesheetsテーブルの代わりに使用します。

ご注意:timesheetsのすべての行は、階層クエリのルート行として、おそらく葉の行と中間行として使用されているので

  1. このクエリは、最高のパフォーマンスを持っていません。これを見ると、サブクエリを比較し、返される行の数と完全なクエリが返す行の数を比較できます。
  2. インデックスをtimesheet_dtに設定し、時間の部分が含まれていないことを確認してから、TRUNCの機能を削除すると、パフォーマンスが向上する場合があります。
  3. 土曜日と日曜日がtimesheetsテーブルに入力されていない場合、この声明が返す最高休暇期間は月曜日から金曜日までの1週間です。これが問題の場合は、CONNECT BY句を調整する必要があります。しかし、これで祝祭日の問題は解決されません。
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

こんにちはヴィンセント、これはそれをしました。 お返事ありがとうございました! –

関連する問題