TL;DR: パラメータで指定されている場合は、join+subselect 全体を削除したいと考えています。
次のようなストアド プロシージャにクエリがあるとします。
open cur_result for
select t1.* from table1 t1
join (select key, value, row_number() over (partition by key order by whatever) rn from table2) t2
on t1.key = t2.key and t2.rn = 1
where [...lots of things...]
and t2.value = 'something'
ご覧のとおり、table1 を table2 に結合するだけではなく、いくつかの基準に基づいて table2 の最初のレコードのみを結合する必要があるため、サブクエリでの row_number 計算と rn=1 の追加の結合条件です。とにかく、これは高価なサブクエリであり、このサブクエリに基づいてフィルタリングしたいということがポイントです。
私の目標は、追加のパラメーターに基づいて、このサブクエリを条件付きにすることです。すべてを繰り返したい場合は、次のようになります。
if should_filter_table2 = 1 then
[the above query is copied here completely]
else
open cur_result for
select t1.* from table1 t1
-- no table2 join
where [...lots of things...]
-- no table2 condition
end if;
問題は、そのようなパラメータが多数存在する可能性があり、ほとんど同じ SQL の分岐が非常に多く、見栄えが悪く、保守が難しいことです。私もこれを行うことができます:
open cur_result for
select t1.* from table1 t1
join (select key, value, row_number() over (partition by key order by whatever) rn from table2) t2
on t1.key = t2.key and t2.rn = 1
where [...lots of things...]
and (should_filter_table2 = 0 or t2.value = 'something')
これは維持するのが簡単ですが、パラメーターがサブクエリが重要ではないことを示している場合でも、サブクエリは無条件で実行されます。私の経験に基づくと、Oracle はこれを最適化できず、パフォーマンスに大きな打撃を与えます。
質問: 1 つのクエリでこれを行うことができますか? このようなもの:
open cur_result for
select t1.* from table1 t1
join {case when should_filter_table2 = 1 then (select key, value, row_number() over (partition by key order by whatever) rn from table2) else [empty table] end} t2
on t1.key = t2.key and t2.rn = 1
where [...lots of things...]
and (should_filter_table2 = 0 or t2.value = 'something')
したがって、 should_filter_table2 が 0 の場合、サブクエリは計算されず、フィルターはまったく適用されません。
動的 SQL は避ける必要があります。動的SQLでこれを行う方法を疑っていますが、同じ保守性の問題が発生します。