私が改善しようとしているコードは次のようになります(簡単な例):
SELECT DISTINCT a.col_a
,COALESCE(b1.col_c, b2.col_c, b3.col_c)
FROM tab_a a
LEFT JOIN tab_b b1
ON a.col_a = b1.col_a
AND b1.col_b = 'blabla1'
LEFT JOIN tab_b b2
ON a.col_a = b2.col_a
AND b2.col_b = 'blabla2'
LEFT JOIN tab_b b3
ON a.col_a = b3.col_a
AND b3.col_b = 'blabla3';
次のスクリプトを使用して、これらのテーブルを再作成できます
CREATE TABLE tab_a(col_a int)
CREATE TABLE tab_b(col_a INT, col_b VARCHAR(10), col_c INT)
INSERT INTO dbo.tab_a ( col_a ) VALUES ( 1 ), ( 2 ), ( 3 );
INSERT INTO dbo.tab_b ( col_a
,col_b
,col_c )
VALUES ( 1, 'blabla1', 1 )
,( 1, 'blabla2', 3 )
,( 1, 'blabla2', 5 )
,( 2, 'blabla2', NULL )
,( 2, 'blabla3', 5 );
どうすれば1結合+多分ウィンドウ関数に変更できますかcoalesce部分を書き換える方法。ただ説明すると、現在の計画では3つのtab_bスキャンが表示されています。これを1に減らします。
SELECT DISTINCT a.col_a
,b.col_c
FROM tab_a a
outer apply (select top 1 b.col_c
from tab_b b
where ((a.col_a = b.col_a
AND b.col_b = 'blabla1' )
or (a.col_a = b.col_a
AND b.col_b = 'blabla2')
or (a.col_a = b.col_a
AND b.col_b = 'blabla3'))
and b.col_c is not null
order by b.col_b)b;
このソリューションには1つのtab_b scan
がありますが、sort
のようにb.col_c
を選択するため、COALESCE
を追加します。上記の例では、このorder
は、order
列の値に対応するjoin condition
のconstants
によって指定されたc
に対応しています。順序が異なる場合は、カスタマイズされたorder by
clauseを記述する必要があるため、状況はさらに複雑になります。
この3つの説明を静的にしたい場合、または以下のようにしたい場合は、以下を実行できます。
一時テーブルまたは変数テーブルに値を挿入しますが、列の形式です https://stackoverflow.com/questions/15745042/efficiently-convert-rows-to-columns-in-sql-server
回答にスクリプトを記述しますが、それらの3つのLEFT JOINを削除し、一時テーブルまたは変数テーブルにCROSS JOINを実行します
データベースモデルを変更して、最も必要なものを満たすこともできます。
支援するには、現在のデータベースモデルを共有してください。次のオプションで作成できます。
SELECT DISTINCT a.col_a
,b1.col_c
FROM tab_a a
LEFT JOIN tab_b b1
ON a.col_a = b1.col_a
AND b1.col_b IN ('blabla1','blabla2','blabla3');
要求に応じて1つの結合^^ IN(..)を使用してややエレガントなスタイルに編集