少し前に、クラスメートがSQLを作成するときに問題に遭遇しました。2つのSQL接続は同じように見えましたが、それらの数は異なっていました。その理由は、左側の接続後のwhere条件がデータをフィルタリングし、データを少なくするためです。sqlの2つの部分は次のとおりです。
select count(1)
from (select *
from KXAPP.I_CASH_LOAN_WHITELIST_C2_V_NEW b
where b.BG_DT < '20180820'
and b.EN_DT >= '20180904') gh
left join (select *
from KXAPP.I_CASH_LOAN_WISH_SCORE
where busi_dt = '20180820') hg
on gh.loan_no = hg.loan_no
select count(1)
from KXAPP.I_CASH_LOAN_WHITELIST_C2_V_NEW b
left join KXAPP.I_CASH_LOAN_WISH_SCORE c
on b.loan_no = c.loan_no
where b.BG_DT < '20180820'
and b.EN_DT >= '20180904'
and busi_dt = '20180820') hg
一見すると、2つのsqlセクションに違いはないように見えます。1つ目は、最初に条件を介してサブテーブルをフェッチしてからリンクすることです。2つ目は、最初にリンクしてから、条件を通過した後にフィルタリングすることです。統計の結果、上部のデータ量が下部のデータ量よりも多いことがわかりました。
実際、これら2つのリンクは異なります。最初のリンクモードでは、メインテーブルはghです。2番目のリンクモードでは、メインテーブルはbです。2番目のリンク方法のデータ量が最初のリンク方法のデータ量より少ない理由は、リンクの結果をフィルタリングするためにリンクの後にwhereが追加されるためです。
説明する例を次に示します。
表Aの構造は次のとおりです。
表Bの構造は次のとおりです。
select *
from (select 1 as a, 2 as b
from dual
union all
select 2 as a, 2 as b from dual) a
left join (select 3 as a, 2 as b
from dual
union all
select 2 as a, 2 as b from dual) b
on a.a = b.a
and b.a = 1;
select *
from (select 1 as a, 2 as b
from dual
union all
select 2 as a, 2 as b from dual) a
left join (select 3 as a, 2 as b
from dual
union all
select 2 as a, 2 as b from dual) b
on a.a = b.a
where b.a = 1;