JOINで行が増える理由と重複チェック(件数確認・1対多の見分け方)

JOINで行が増える理由と重複チェック(件数確認・1対多の見分け方)

この記事で分かること

  • JOIN後に「件数が合わない」「同じ行が何度も出る」とき、原因を切り分けられる
  • 結合と結合の件数を確認する手順が身につく
  • 1対多・多対多の関係を意識して、JOIN条件を足す・見直す判断ができる

結論:結合前後の件数を必ず確認する

JOINは「条件に合う組み合わせ」をすべて出します。1対多の「多」側を結合すると行数は増えます。意図した結合なら問題ありませんが、「条件不足で意図せず増えている」のか「1対多で増えているだけ」なのかを、結合前の各表の件数結合後の件数で確認すると原因が絞れます。

最小例:結合すると行が増える

顧客(customers)と注文(orders)は 1対多 です。1人に注文が複数あるため、JOINすると行数は「注文の数」になります。

-- 結合後の件数は「注文の数」(顧客数より多くなりがち)
SELECT c.name, o.total
FROM customers AS c
JOIN orders AS o ON o.customer_id = c.id;
  • 意図どおり: 「1行=1注文」で、顧客名と注文金額が欲しい → 上記でOK
  • 意図と違う: 「1行=1顧客」で、顧客ごとの合計が欲しい → 先に集計(GROUP BY)してから扱う

結合前後の件数確認(まずここをやる)

  1. 結合する各表を単体で SELECT COUNT(*) する
  2. 結合後の結果SELECT COUNT(*) する(または件数が分かる方法で確認)
  3. 結合後が「どれかの表より明らかに多い」→ 1対多の多側を結合している、または JOIN 条件が足りていない
-- 例:顧客10件、注文50件 → JOIN後は50行が自然
SELECT COUNT(*) FROM customers;  -- 10
SELECT COUNT(*) FROM orders;     -- 50
SELECT COUNT(*) FROM customers c JOIN orders o ON o.customer_id = c.id;  -- 50

結合後が 10 でも 50 でもなく、異常に大きい(例:500)場合は、JOIN条件の不足(同じキーで複数紐づく・条件が甘い)を疑います。

よくあるミス

  • 結合後の件数を見ずに「動いた」で終わる
  • 「1行=何か」を決めずにJOINする(顧客単位か注文単位かで、GROUP BY が必要かが変わる)
  • 複数回JOINするときに、途中の件数を確認しない(2つ目・3つ目のJOINで一気に増えることがある)

練習問題(2問)

  1. 顧客と注文をJOINしたとき、結合前(顧客数・注文数)と結合後の件数を出し、関係を確認する
  2. 「顧客ごとに注文数が2件以上の顧客」を取りたいとき、JOINだけでは足りず GROUP
    BY と HAVING が必要になる理由を、件数の観点で説明する

次に読む

タイトルとURLをコピーしました