1

大きなクエリがあります (私が書いたものではありませんが、いくつか変更を加えています)。私を悩ませていることの 1 つは、約 4 か所で同じ COALESCE 関数を使用していることです。おそらくDUALからの選択に参加することによって、それを除外する方法はありますか? それを因数分解すると、パフォーマンス上の利点はありますか?

少し太字にしたクエリを次に示します。

select 
tbl1.gid
[snip]
         ,COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
        ,t1_end_dt
FROM    tbl1
....
JOIN    tbl2               ON (t2_pk          = wpck_wrkr_id  AND
                                            t2_ind_1    ='Y'    AND
        COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) 
        BETWEEN  t2_strt_dt AND t2_end_dt)
JOIN    tbl3                ON (t3_pk               = t2_fk_t3_pk AND
       COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) 
        BETWEEN t3_strt_dt AND t3_end_dt)    
LEFT JOIN tbl4 tbl4_a             ON (tbl4_a.t4_pk         = chkw_wkt_id)
.....
GROUP BY tbl1.gid 
.....
        ,COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt)
        ,COALESCE(tbl4_b.t4_or_id, tbl4_a.t4_or_id, t7_or_id )
        ,t1_end_dt
ORDER BY perd_end_dt

SELECT で pred_end_dt という名前を付け、ORDER BY でその名前で参照することにより、COALESCE の 1 つを既に除外していることに注意してください。

4

4 に答える 4

2

GROUP BY 句のオカレンスを列エイリアスに置き換えることができるはずですperd_end_dt。ただし、JOIN 条件でのオカレンスでは、列エイリアスを使用できません。

これは、パフォーマンスに影響を与えます。JOIN 条件は、現在書かれている方法ではインデックスを使用できないと思います。ただし、JOIN 条件では 1 項のみであるため、影響は非常に小さい可能性があります。つまり、t2_pkおよびを含む用語t2_ind_1はすでに行セットを削減している可能性があるため、日付の比較では小さなセットのみを処理する必要があります。これは、話している行の数と、データがどのように分散されているかによって異なります。

COALESCE()を除外してインデックス作成を利用する 1 つの方法は、その式の結果である冗長な列を作成することです。トリガーを使用して、挿入または更新のたびに正しい値になるようにします。次に、列にインデックスを付けます。

しかし、私が言ったように、それは価値があるよりも面倒かもしれません. この変更により、コードがより保守しやすくなり、より正確になり、より高速になることを確認する必要があります。


もう 1 つのオプションはCOALESCE()、サブクエリで式のエイリアスを定義することです。テーブルエイリアスで修飾していないため、列がどのテーブルからのものかわかりません。しかし、それらがすべての列であると仮定できる場合tbl1:

...
FROM (
    SELECT COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) perd_end_dt,
      t1_fk_t2_pk
    FROM tbl1) t1
  JOIN tbl2
    ON (tbl2.t2_pk = t1.t1_fk_t2_pk AND tbl2.t2_ind_1 = 'Y'
      AND t1.perd_end_dt BETWEEN tbl2.t2_strt_dt AND tbl2.t2_end_dt)
...
于 2009-01-16T18:36:48.157 に答える
1

仮想テーブルを作成できます

(Select Coalesce( all your stuff ....) perdEndDt 
   From [all your tables necessary for this one value])

これを個別の結合テーブルとしてSelectSQLに含めます

  Select [all yr other stuff,
      Z.perdEndDt
  From [Other Tables Joined together]
      Join 
         (Select Coalesce( all your stuff ....) perdEndDt,
               [other columns necessary for join conditions]
         From [all your tables necessary for this one value]) As Z
         On [Join conditions for Z to other tables]
  Where  [any filter predicates]
  Order By Z.perdEndDt
     ... etc.  
于 2009-01-16T18:38:56.170 に答える
1

多分あなたはwith句を使うことができますか?

with data as
(
   select COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
   ,      .....
   ,      ...
   from   tbl1
)
select ...
from   data
,      ....
where  ....
于 2009-01-16T18:33:45.167 に答える
1

オラクルにはビューがありますか? (そうしなければなりません。) そのCOALESCE()式をさまざまな場所で使用していることに気付いた場合VIEWは、元のテーブルの代わりに を作成して使用する価値があるかもしれません。その下で同じ計算が実行されますが、クエリの構文はより簡潔になり、より明確になります。

私の考え方では、「ビュー」はデータベースの「テーブル」であり、「関数」はプログラムの「コード行」です。同様のロジックを使用するクエリが多数ある場合は、共通のロジックを除外するビューを作成し、代わりにそれを使用します。

于 2009-01-16T19:38:45.567 に答える