2016-12-11 9 views
2

OR条件付きのルックアップテーブル(15万以上の行)に巨大なテーブル(1,000万以上の行)を参加させる必要があります。ような何か:table1にNULLとしてcまたはdを持つことができる、と私は残りの部分を残して、利用できる方に参加したいのでORシフト付きの効率的なJOIN節

SELECT t1.a, t1.b, nvl(t1.c, t2.c), nvl(t1.d, t2.d) 
FROM table1 t1 
JOIN table2 t2 ON t1.c = t2.c OR t1.d = t2.d; 

はこれがあります。クエリプランには、Nested Loopがあると言います。これはORの条件のためです。この問題を解決するきれいで効率的な方法はありますか?私はRedshiftを使用しています。

編集:これをUNIONで実行しようとしていますが、以前より速くはないようです。

+0

クエリプランを共有できますか? – greginvm

+0

重複が問題にならない場合は、 'union all'を使用することをお勧めします。 – systemjack

答えて

0

あなたが好きな列を持っているなら、NVL()(別名COALESCE())とそれに加わることができます。

SELECT t1.a, t1.b, nvl(t1.c, t2.c), nvl(t1.d, t2.d) 
FROM table1 t1 
JOIN table2 t2 
    ON t1.c = NVL(t2.c,t2.d); 

私はまた、あなたが大きなテーブルが再配布されていないことを保証するためにDISTSTYLE ALLにルックアップテーブルを設定する必要があることをお勧めしたいです。

[また、Redshiftでは1000万行は大きくありません。数千億行のテーブルを照会(および結合)しても、Redshiftで優れたパフォーマンスが得られるというだけでは駄目ではありません。 ]

0

2つ(左)の結合はどうですか?小さなルックアップテーブルのパフォーマンスでも、あまりにも悪くはありません。

SELECT t1.a, t1.b, nvl(t1.c, t2.c), nvl(t1.d, t3.d) 
FROM table1 t1 
LEFT JOIN table2 t2 ON t1.d = t2.d and t1.c is null 
LEFT JOIN table2 t3 ON t1.c = t3.c and t1.d is null 

元のクエリでは、ルックアップテーブルのcまたはdの少なくとも1つに一致する行のみが返されます。それが保証されていない場合は、フィルタを追加する必要があるかもしれません。たとえば、c1とdの両方がnullであるか、table2に値がないt1の行があります。

実際には、ジョインでnullチェックは必要ありませんが、少し速いかもしれません。

関連する問題