2017-02-03 15 views
0

数年前に書かれたクエリでいくつか混乱をきれいにして、以下のクエリが結果を遅くする原因であることに気付きました。私は代替案を探すことを試みたが、それほど成功しなかった。左結合のSQLクエリが遅くなります

WITH cat 
    AS (SELECT main.category_id main_id, 
       main.description main_desc, 
       sub1.category_id sub1_id, 
       sub1.description sub1_desc, 
       sub2.category_id sub2_id, 
       sub2.description sub2_desc, 
       sub3.category_id sub3_id, 
       sub3.description sub3_desc, 
       NVL (
        NVL (NVL (sub3.category_id, sub2.category_id), 
         sub1.category_id), 
        main.category_id) 
        lowest 
      FROM iod.sr_category main 
       -- We need to insert a temporary null row and include it in the join so the categories which are not leaves are also included 
       LEFT JOIN 
       (SELECT category_id, description, parent_id 
        FROM iod.sr_category 
       UNION 
       SELECT NULL, NULL, NULL 
        FROM DUAL) sub1 
        ON ( main.category_id = sub1.parent_id 
         OR sub1.category_id IS NULL) 
       LEFT JOIN 
       (SELECT category_id, description, parent_id 
        FROM iod.sr_category 
       UNION 
       SELECT NULL, NULL, NULL 
        FROM DUAL) sub2 
        ON ( sub1.category_id = sub2.parent_id 
         OR sub2.category_id IS NULL) 
       LEFT JOIN 
       (SELECT category_id, description, parent_id 
        FROM iod.sr_category 
       UNION 
       SELECT NULL, NULL, NULL 
        FROM DUAL) sub3 
        ON ( sub2.category_id = sub3.parent_id 
         OR sub3.category_id IS NULL) 
      WHERE  main.parent_id IS NULL 
       AND (main.category_id IN (:main_category)) 
       AND ( NVL (:sub_category1, 0) = 0 
        OR sub1.category_id = :sub_category1) 
       AND ( NVL (:sub_category2, 0) = 0 
        OR sub2.category_id = :sub_category2) 
       AND ( NVL (:sub_category3, 0) = 0 
        OR sub3.category_id = :sub_category3)) 
    SELECT r.sector_report_id, 
     r.created_date report_created_date --, nvl(f.sch_dep_date_local_port, f.sch_dep_date_gmt) report_search_date 
              , 
     c.main_desc, 
     c.sub1_desc, 
     c.sub2_desc, 
     c.sub3_desc, 
     p.problem_type_code, 
     p.description, 
     e.first_name, 
     e.last_name, 
     e.employee_id, 
     cl.description class, 
     ROW_NUMBER() 
     OVER (PARTITION BY r.sector_report_id, cl.class_id 
       ORDER BY q.question_id) 
      question_num, 
     q.label question, 
     q.data_type, 
     NVL (
      pa.answer, 
      NVL (
       a.VALUE, 
       NVL (a.free_text, 
        NVL (a.hours || ':' || a.minutes, 'NO ANSWER')))) 
      answer, 
     f.arln_code, 
     f.flight_number, 
     f.sch_dep_date_gmt, 
     f.sch_dep_date_local_port, 
     f.sch_dep_apt, 
     f.sch_arv_apt, 
     f.tail_number, 
     f.fleet_code, 
     LISTAGG (
       e_cmt.first_name 
      || ' ' 
      || e_cmt.last_name 
      || ' ' 
      || cmt.created_date 
      || ':' 
      || cmt.comment_text, 
      ' ' || CHR (10)) 
     WITHIN GROUP (ORDER BY cmt.created_date) 
      comments, 
     (NVL ((SELECT COUNT (*) 
        FROM iod.sr_photograph p 
        WHERE p.sector_report_id = r.sector_report_id), 
       0)) 
      AS photo 
    FROM iod.sr_sector_report r 
     JOIN cat c ON c.lowest = r.category_id 
     LEFT JOIN iod.sr_problem_type p 
      ON p.problem_type_id = r.problem_type_id 
     LEFT JOIN iod.ops_flight_leg f 
      ON f.ops_flight_leg_id = r.ops_flight_leg_id 
     LEFT JOIN iod.employee e ON e.employee_id = r.employee_id 
     LEFT JOIN iod.sr_class_sector_report csr 
      ON csr.sector_report_id = r.sector_report_id 
     LEFT JOIN iod.sr_class cl ON cl.class_id = csr.class_id 
     LEFT JOIN iod.sr_answer a ON a.sector_report_id = r.sector_report_id 
     LEFT JOIN iod.sr_predefined_answer pa 
      ON pa.predefined_answer_id = a.predefined_answer_id 
     LEFT JOIN iod.sr_question q ON q.question_id = a.question_id 
     LEFT JOIN iod.sr_comment cmt 
      ON cmt.sector_report_id = r.sector_report_id 
     LEFT JOIN iod.employee e_cmt ON e_cmt.employee_id = cmt.employee_id 
    WHERE  (NVL (:problem_type, 0) = 0 OR p.problem_type_id = :problem_type) 
     AND TRUNC (f.sch_dep_date_local_port) BETWEEN :from_date AND :TO_DATE 
     --and cast(nvl(f.sch_dep_date_local_port, f.sch_dep_date_gmt) as date) between :from_date and :to_date 
     AND (--nvl(:station_from, ' ') = ' ' or 
       f.sch_dep_apt IN (:station_from)) 
     AND (--nvl(:station_to, ' ') = ' ' or 
       f.sch_arv_apt IN (:station_to)) 
GROUP BY r.sector_report_id, 
     r.created_date, 
     c.main_desc, 
     c.sub1_desc, 
     c.sub2_desc, 
     c.sub3_desc, 
     p.problem_type_code, 
     p.description, 
     e.first_name, 
     e.last_name, 
     e.employee_id, 
     cl.description, 
     cl.class_id, 
     q.label, 
     q.data_type, 
     q.question_id, 
     NVL (
      pa.answer, 
      NVL (
       a.VALUE, 
       NVL (a.free_text, 
        NVL (a.hours || ':' || a.minutes, 'NO ANSWER')))), 
     f.arln_code, 
     f.flight_number, 
     f.sch_dep_date_gmt, 
     f.sch_dep_date_local_port, 
     f.sch_dep_apt, 
     f.sch_arv_apt, 
     f.tail_number, 
     f.fleet_code 
ORDER BY TRUNC (f.sch_dep_date_local_port) ASC 

ので

subx.category_id = suby.parent_id OR suby.category_id is null 

部分は、クエリを遅くします。何か案は?

+0

謝罪。急いで質問を提出し、推奨タグを取り上げました。 :) – user3200361

+0

それはなぜスタックオーバーフローがより良い仕事をしないのかの質問をする。これをOracleと識別するのは簡単です。 –

+0

それは本当です。私は単語認識アルゴリズムのための全く新しい質問を提起し、stackoverflowの注意を得ることができます。 :) – user3200361

答えて

0

実行されているビジネスロジックの説明や説明がなくても、私たちができることはすべて推測です。しかし、これは、サブクエリ・ファクタリングが役立つシナリオのように見えます。

with sub as (
    SELECT category_id, description, parent_id FROM sr_category 
    UNION 
    SELECT null, null, null FROM DUAL) 
select 
    .... 
from 
    .... 
LEFT JOIN sub sub1 
    ON (main.category_id = sub1.parent_id OR sub1.category_id is null) 

    LEFT JOIN sub sub2 
    ON (sub1.category_id = sub2.parent_id OR sub2.category_id is null) 

    LEFT JOIN sub sub3 
    ON (sub2.category_id = sub3.parent_id OR sub3.category_id is null) 

    WHERE main.parent_id is null 
    AND (main.category_id IN (:main_category)) 
    AND (nvl(:sub_category1, 0) = 0 OR sub1.category_id = :sub_category1) 
    AND (nvl(:sub_category2, 0) = 0 OR sub2.category_id = :sub_category2) 
    AND (nvl(:sub_category3, 0) = 0 OR sub3.category_id = :sub_category3)) 

WITH句については、Oracle SQLのマニュアルに記載されています。 Find out more

+0

こんにちは私は質問全体を更新しました。それが役立つだろう? :) – user3200361

関連する問題