2つのテーブルから共通したIDを除いたものを抽出する方法
最近、Squeakさわれてません。。。
4月に入ると落ち着くはずなので、そこから再開予定。。。
で、タイトルの件ですが、みなさんどうされているのかなと思って書いてみた。
例:(例が悪かったらごめんさい。)
AテーブルとBテーブルがあって、共通のIDがあるものとする。
(顧客マスタと営業履歴があって、共通のコーポレートIDみたいなのだとイメージしやすいかな?)
Bテーブルに含まれているIDを除いたID一覧を取得するにはどうしたら良いか?
(顧客マスタにはあるけど、営業履歴にはない(営業にいったことがない)顧客を抽出したいイメージです。)
以下の例は、PostgreSQLで記載するものです。mysqlとかだとさっぱりなので、他に書く方法があると思いますので、
ぜひぜひツッコミまってます。
パターン1
安直にいくパターン。いわゆるNOT IN。コストは高。
(たぶんテーブル内にNULLデータがあると正しく動いてくれないパターン。まぁ、IDはNOT NULLだと思うけど)
SELECT * FROM TABLE.A where id NOT IN ( SELECT id FROM TABLE.B GROUP BY cid )
パターン2
JOINして弾くパターン。(自分はよく使います)
SELECT * FROM TABLE.A a LEFT JOIN TABLE.B b USING (id) WHERE b.id is null
パターン3
NOT EXISTSを使うパターン。
SELECT * FROM TABLE.A a where NOT EXISTS ( SELECT * FROM TABLE.B b WHERE a.id = b.id )
がよく使われそうな気がするんですが、他にもあるかな?
ちなみにNOT EXISTSはテーブルが3つになったらどうするのがコストが安いのかは今眠いので、
あんまり頭が回らない。。。
(顧客マスタ、営業履歴、メール配信が絡んできて、営業行ったことないけど、メール配信した企業は除くイメージ)
自分の方法だと、
SELECT * FROM TABLE.A a LEFT JOIN TABLE.B b USING (id) LEFT JOIN TABLE.C c USING (id) WHERE b.id IS NULL c.id IS NULL
で、NOT EXISTSだと。。。
こんなのでいいのか?
SELECT * FROM TABLE.A a where NOT EXISTS ( SELECT * FROM TABLE.B b WHERE a.id = b.id ) AND NOT EXISTS ( SELECT * FROM TABLE.C c WHERE a.id = c.id )
これは、イケてないな。。。コスト高そう。。。自分ダメな奴です。。。でもORM使えませんw
ちなみに、idはINDEX張っちゃうと意外にNOT INでもそこまで遅くないという。。。
LEFT JOINが自分はスッキリして、追加もしやすい印象ですが、みなさんどうでしょうか?