0Pricing
Coding Interview Prep · レッスン

3つ以上のテーブルをJOINする

JOINを連結し、中間結果セットについて考える方法を学びます。

「3つ以上のテーブルをJOINする」はCoddyKit上の無料Coding Interview Prepレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはCoding Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Coding Interview Prepコースには全4レッスンが含まれています。

結合は分岐ではなく連鎖する

実際の面接問題が2つのテーブルだけで終わることは、ほとんどありません。3つ、4つ、それ以上のテーブルを結合するよう求められます。複雑さを整理する重要な考え方は、複数テーブルの結合は、2テーブルの結合を順番に行うだけだということです。

データベースはまず最初の2つを中間結果に結合し、その結果を3つ目のテーブルに結合するという処理を繰り返します。1つの結合について考えられるなら、その連鎖についても考えられます。

3テーブルスキーマ

例を3つ目のテーブルまで拡張します。これで、顧客、顧客の注文、そして各注文が参照する商品を扱います。

  • customers(id, name)
  • orders(id, customer_id, product_id, amount)
  • products(id, title)

これらを結ぶリレーションシップは2つあります。orders.customer_id = customers.id と orders.product_id = products.id です。

customers(id, name)
orders(id, customer_id, product_id, amount)
products(id, title)

基本的な3テーブルクエリ

JOINを順番に重ねます。それぞれの JOIN ... ON はテーブルを1つ追加し、それまでのテーブルとどのようにつながるかを示します。

上から下へ読みます。まず orders から始め、一致する顧客を結合し、次に一致する商品を結合します。すべての注文行に、顧客名と商品タイトルが追加されます。

SELECT c.name, p.title, o.amount
FROM orders o
JOIN customers c ON c.id = o.customer_id
JOIN products  p ON p.id = o.product_id;

中間結果セットで考える

複数テーブルの結合を簡単にする考え方は、各JOINの後で、それまでの中間結果を思い浮かべることです。

  • 1回目の結合後: orders + 顧客の列
  • 2回目の結合後: その結果 + 商品の列

次のON句では、中間セットにすでに存在する任意の列を参照できます。そのため、結合の順序によって各ON句に記述できる内容が変わります。

各ON句から先行するテーブルが見える

重要な帰結があります。後続の結合のON句では、追加するテーブルだけでなく、それより前に結合した任意のテーブルを参照できます。

ここでは、3つ目の結合が、すでにスコープ内にある o(orders)とつながっています。c と p もすでに途中までの結果に含まれているため、4つ目のテーブルをどちらかに結合することもできます。

SELECT c.name, p.title, w.region
FROM orders o
JOIN customers c ON c.id = o.customer_id
JOIN products  p ON p.id = o.product_id
JOIN warehouses w ON w.id = o.warehouse_id; -- refers to o

中心となるテーブルから始める

ライブ面接で役立つ実践的なコツは、FROMをファクト/中心テーブル(通常はリレーションシップの中央にあるテーブル)から始め、そこからルックアップテーブルへ向かって広げることです。

Orders は customers と products の両方への外部キーを持つ中心に位置するテーブルなので、ここから始めると、すべてのON句をシンプルに先行参照の形で書けます。

-- orders is central: it links to both sides
FROM orders o
JOIN customers c ON c.id = o.customer_id
JOIN products  p ON p.id = o.product_id

連鎖全体でファンアウトが累積する

ファンアウトについて学んだことはすべて引き続き当てはまり、しかも累積します。各注文に複数の商品があり、各商品に複数の税行がある場合、行数は各段階で掛け合わされます。

複数の結合を含むクエリで集計値が大きすぎる場合は、途中の結合のどれかでファンアウトが発生していないかを疑い、各結合の粒度を個別に確認してください。

-- rows = orders * items_per_order * tax_rows_per_item
SELECT o.id
FROM orders o
JOIN order_items i ON i.order_id = o.id
JOIN item_taxes  t ON t.item_id  = i.id;

連鎖の中で結合タイプを混在させる

1つのクエリでINNER JOINとLEFT JOINを組み合わせることはできますが、順序が重要です。LEFT JOINによってNULLが導入された後、そのNULL列を参照する後続のINNER JOINによって、保持されていた行が削除されることがあります。

この例では、注文のない顧客はLEFT JOINによってNULLの product_id とともに保持されますが、続く products へのINNER JOINによって再び除外されます。プレッシャーのかかる場面では、起こしやすいミスです。

SELECT c.name, p.title
FROM customers c
LEFT JOIN orders  o ON o.customer_id = c.id
JOIN products p ON p.id = o.product_id;
-- the INNER products join can cancel the LEFT JOIN

外部結合を外部結合のまま保つ

注文のない顧客を最後まで保持するには、後続の結合もLEFTにします。そうすれば、NULLが安全に最後まで流れます。

経験則として、いったん外部結合にしたら、任意ブランチから派生するすべてのテーブルについて外部結合のままにしてください。

SELECT c.name, p.title
FROM customers c
LEFT JOIN orders   o ON o.customer_id = c.id
LEFT JOIN products p ON p.id = o.product_id;
-- customers with no orders are now kept (NULL title)

規模が大きくなるとエイリアスが不可欠になる

4つまたは5つのテーブルを扱うと、複数のテーブルが id、name、created_at のような列名を共有することがあります。短く一貫したエイリアスを使うと、曖昧さを防ぎ、クエリを読みやすくできます。

テーブルを示すエイリアス(c、o、p)を選び、すべての列を修飾してください。面接官は、エイリアスの付け方から、本番用SQLをどのように書くかを判断します。

SELECT c.id   AS customer_id,
       o.id   AS order_id,
       p.id   AS product_id,
       p.title
FROM orders o
JOIN customers c ON c.id = o.customer_id
JOIN products  p ON p.id = o.product_id;

多対多の関係にブリッジテーブルを使う

2つのエンティティが多対多の関係にある場合、その間に3つ目の中間(ブリッジ)テーブルを置き、そのテーブルを介して結合します。学生とコースは enrollments を介してつながります。

ブリッジテーブルを経由する必要があると見抜くこと自体が、面接でよく見られる評価ポイントです。

SELECT s.name, c.title
FROM students s
JOIN enrollments e ON e.student_id = s.id
JOIN courses     c ON c.id = e.course_id;

クイックチェック

結合タイプが混在する連鎖について考えてみましょう。

まとめ: 3つ以上のテーブルを結合する

面接では次の点を押さえておいてください。

  • 複数テーブルの結合は2テーブル結合の連鎖です。各段階の後で中間結果について考えてください。
  • 後続のON句では、連鎖内の先行する任意のテーブルを参照できます。
  • 中心テーブルから始め、ルックアップテーブルへ広げていきます。
  • 結合をまたぐとファンアウトが累積するため、各段階で粒度を確認してください。
  • LEFT JOINの後にINNER JOINを置くと、LEFT JOINの効果を打ち消すことがあります。任意の行を保持するには、外部結合のままにしてください。
  • 多対多の関係はブリッジテーブルを介して結合します。

よくある質問

「3つ以上のテーブルをJOINする」レッスンは無料ですか?

はい。「3つ以上のテーブルをJOINする」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Coding Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Coding Interview Prepコースには全4レッスンが含まれています。

「3つ以上のテーブルをJOINする」で何を学びますか?

JOINを連結し、中間結果セットについて考える方法を学びます。 ブラウザで直接実行するハンズオンコードでCoding Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Coding Interview Prepを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのCoding Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「3つ以上のテーブルをJOINする」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このCoding Interview Prepレッスンでコードを書いて実行できますか?

はい。すべてのCoding Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. INNER JOINが行を照合する仕組み
  2. JOINにおけるONとWHEREの違い
  3. JOINのファンアウトと行の増加
  4. 3つ以上のテーブルをJOINする
← Coding Interview Prepに戻る