SQL の JOIN を図解:INNER JOIN と LEFT JOIN で行が組になる様子を再生で見る
SQL の JOIN は、2 つの表の行を組にして、1 行にする操作です。
下のボードは、顧客 8 人・注文 12 件の小さな店のデータベースにつながっています。SQL を書き換えて実行すると、図と結果がその場で変わります。
SQL を書き換えて試す
図の表と表を結ぶ線の上の「JOIN」を押すと、結合の種類を選んで、行が組になる様子を再生できます。
JOIN は、ON が真になった組だけを残す
customers の行と orders の行を 1 つずつ突き合わせ、ON の条件(o.customer_id = c.id)が真になった組だけが、結果の 1 行になります。 注文の無い Ana Ruiz と Ken Aoki は、どの注文とも組にならないので、結果に出てきません。
図は顧客 4 人に絞って再生しています。データ全体では、結果は 12 行です。
LEFT JOIN は、相手のいない左の行も残す
LEFT JOIN は、左に書いた表(FROM の customers)の行を全部残します。 組になる注文が無い Ana Ruiz と Ken Aoki も 1 行ずつ残り、orders の列は NULL(値が無いという印)で埋まります。 データ全体では、JOIN の 12 行に 2 人の 2 行が加わって 14 行です。
相手のいない行だけを取り出すときは、この NULL を手がかりにします。 ボードの見本の「注文の無い顧客」は、LEFT JOIN のあとに WHERE o.id IS NULL で、注文の列が NULL の行だけを選んでいます。
JOIN で行が増える理由
JOIN の説明によく使われるベン図は、どちらの表の行が残るかを表します。ただ、行と行の組がいくつできるかは表せません。 Liam Carter には注文が 3 件あるので、ON が真になる組が 3 つでき、結果に Liam Carter が 3 行並びます。
つないだ結果を数えるときは、この繰り返しに気をつけます。LEFT JOIN のあとに count(*) で数えると、注文の無い顧客も NULL で埋まった 1 行を数えて 1 になります。 ボードの見本の「顧客ごとの注文数」は count(o.id) で数えて、注文の無い顧客を 0 にしています。
LEFT JOIN の条件は、ON と WHERE で結果が変わる
右の表への条件を WHERE に書くと、組を作ったあとで行を絞ります。 相手のいない行は o.status が NULL なので o.status = 'shipped' が真にならず、その顧客は結果から落ちます。ON に書くと、組を作るときの条件になります。発送済みの注文が無い顧客も、注文の列を NULL にして残ります。
図は顧客 4 人に絞って表示しています。
結合の種類と、残る行
| 書き方 | 残る行 | このデータでの行数 |
|---|---|---|
| JOIN (INNER JOIN) | ON が真になった組だけ | 12 |
| LEFT JOIN | 左の表の行は全部(相手がいなければ右の列を NULL に) | 14 |
| RIGHT JOIN | 右の表の行は全部(相手がいなければ左の列を NULL に) | 12 |
| FULL JOIN | 両方の表の行は全部 | 14 |
| CROSS JOIN | ON を書かず、すべての組(左の行数 × 右の行数) | 96 |
注文はどれも顧客を持っている(customer_id は NOT NULL で、customers を参照する)ので、このデータでは RIGHT JOIN は JOIN と、FULL JOIN は LEFT JOIN と同じ行数になります。
よくある質問
JOIN と INNER JOIN は同じですか?
同じです。JOIN とだけ書くと INNER JOIN になります。
LEFT JOIN と LEFT OUTER JOIN の違いは何ですか?
違いはありません。OUTER は省略できる語で、LEFT JOIN と書いても LEFT OUTER JOIN と書いても同じ結果です。
JOIN すると行が増えるのはなぜですか?
ON の条件が真になる組の数だけ行ができるからです。注文が 3 件ある顧客は、注文の行と 3 つの組を作るので、結果に 3 行出ます。
相手のいない行だけを取り出すにはどうしますか?
LEFT JOIN でつないだうえで、右の表の主キーが NULL の行を WHERE で選びます(WHERE o.id IS NULL)。相手のいない行は、右の表の列がすべて NULL で埋まっているからです。
RIGHT JOIN と FULL JOIN は何が違いますか?
RIGHT JOIN は右の表の行を全部残します。表の順番を入れ替えて LEFT JOIN にしても、同じ行が返ります(列の並びは変わります)。FULL JOIN は左右どちらの行も全部残し、相手のいない側を NULL で埋めます。
JOIN をベン図で説明してもよいですか?
どちらの表の行が全部残るかを示すには使えます。ただ、ベン図では行と行の組がいくつできるかが表せないので、1 人の顧客に注文が 3 件あると結果が 3 行になることは読み取れません。
SQL を順に学ぶ
WebTerm Learn の SQL 入門編と基礎編(どちらも公開の準備中)は、このボードで SQL を組み立てながら、SELECT から JOIN・GROUP BY・サブクエリまでをゲームのように順に進めるコースです。 どのコースから始めるかは SQL の学び方ガイド にまとめています。
データは WebTerm Learn の SQL 入門編で使っている店のデータベースです。実行は PostgreSQL の動きに合わせたブラウザの中のシミュレーションで、ボードで書き換えたデータはこのページを開き直すと元に戻ります。