こんにちは。
この度初めて投稿させていただきます。
SQLのテーブル結合について、私が調べた内容のまとめです。
環境: SQL Server 2012
こちらも合わせてどうぞ
次回記事
テーブル結合についての備忘録 その2
まだまだ駆け出しの新人PGですが、
SQLでのテーブル結合を業務で使う機会がありました。
「テーブル結合は3種類ある。」
「JOINするときはONに条件を書いとけばいい」
くらいのな~んとなくしかテーブル結合について解っておらず、
思い通りのデータを抽出することが出来ずに大変と四苦八苦いたしました。
今日は一日中SQLについて調べ倒したのですが
ネットには誤った情報も多く何が正しいのかがわからずに右往左往と惑わされました。
しかし時間を費やした甲斐もあり、ようやく自分の中で結論が出せて、
テーブル結合の仕組みがある程度見えてきた気がします。
今、四苦八苦とした思い出が頭の中に記憶として残っているうちに
後から、四度八度と読める記録として残しておくことにします。
#結合処理のロジックについて
まずは2つのテーブルが結合される際に
どういった流れで結合がされるのかを理解する必要があります。
重要な流れは以下になります。
①ON句の条件でテーブル結合が行われる。
②WHERE句の条件で抽出が行われる。
この知識を前提としたときに、次のような会話がありました。
先輩SE1「WHERE句でテーブル結合なんかしたら駄目だよ!
10万件のデータと10万件のデータのテーブル同士をくっ付けるとすごく無駄になるよ!」
私「なるほど! 先に結合のときに件数を減らしとくわけですね!」
という訳でまだ何も解っていなかった私は以下のようなSQLを組みました。
SELECT
a.name
, b.name
FROM a
LEFT OUTER JOIN b
ON a.b_cd = b.cd
AND b.cd = '1'
--b.cdはbのPK
我々、新米PG達には以上のSQLで、b.cd = '1'の一意なデータが得られるように見えるでしょう。
しかし、経験あるSE, PGの方々には一目瞭然でこのSQLの危険性が読み取れるかと思います。
#LEFT OUTER JOINについて
結論から言うと、先程のSQLでは一意なデータを得ることができません。
よく他のサイトではINNER JOINからの説明に入ることが多いのですが、
私の主観で、LEFT OUTER JOINの説明から入ります。
LEFT OUTER JOINでは(LEFT OUTER JOINの)左側のテーブルの行を必ず全て、「呼出」します。
この時、右側のテーブルに存在しない行についてはNULLが埋められていきます。
先ほどのコードでいうと、
FROM a -- ← 左側
LEFT OUTER JOIN b -- ← 右側
ON a.b_cd = b.cd
AND b.cd = '1'
という位置付けになります。
その結果、こんなデータが取れてしまいます。
cd | name |
---|---|
1 | ほげほげ |
2 | NULL |
3 | NULL |
実際に技術的な単語としては正しいとは言えないと思いますが
ここで、**「抽出」ではなく、「呼出」**という言葉を用いたのには理由があり、
これから説明しますがイメージをつけやすくする為です。
ここでまた、少し話が先ほどのTOPICに戻るのですが次の点も重要になります。
ON句:結合条件
WHERE句:抽出条件
であるという事です。
つまり、これらの点をまとめると、
先ほどのコードを書いたときには次のような処理が行われていきます。
①ON句の結合条件で、テーブル結合が行われる。(この時はデータは一意。)
②LEFT OUTER JOINで左のテーブルの行を全て呼び出す。
結果、取得する必要の無い行もNULLが埋められて呼び出しされる。
という訳です。
LEFT OUTER JOINを理解していない者のイメージとしては、
結合条件へ「行を抽出する条件」を書くことで、
その行だけが結合されるようなイメージを持ってしまいます。
実際の処理としてはその行だけが結合されて、残りはNULL埋めされているのですが、
ここでは**「呼出」という言葉を用いることで
結合条件を指定していようが、どうしようが
左のテーブルの全行が呼び出される**という事を示唆しました。
ちなみにON句に書かれる条件は、
左側のテーブルに関する条件であろうが、
右側のテーブルに関する条件であろうが、
両側のテーブルに関する条件であろうが、
問答無用で左側のテーブルの全行が**「呼出」**される事になります。
ネット上でもこの「結合条件」という言葉に惑わされている方々の記事が
あちこち多くに散見されました。
では本当にデータを「抽出」する為には、
どういったSQLをかけばいいのでしょうか?
抽出という言葉を用いたことで、
皆さんもある程度予想がついている事とは思います。
SELECT
a.name
, b.name
FROM a
LEFT OUTER JOIN b
ON a.b_cd = b.cd
WHERE
b.cd = '1'
その名の如く、
抽出条件はWHEREへ書くことで一意なデータを得ることが出来ます。
とりあえず今回重要だった事は、
LEFT OUTER JOINでは、ONでデータの抽出は出来ない。
これだけは皆さん頭に必ず残しておいてください。
あまり使う機会はないと思いますがRIGHT OUTER JOINも同様のはずです。
しかし、これでまだ終わりではありません
続きは次の記事で書きます。
テーブル結合についての備忘録 その2
これから業務等でテーブル結合をすることになる皆様の
お力になれれば幸いです。