💥

💥「データが足りない…」結合条件ミスで本番直前に焦った話

に公開

📌 本記事は実体験をもとに、ChatGPTの協力を得て執筆しました。

これは、僕がデータ分析基盤のデータマートを構築していたときの話です。
そのとき担当していたのは、「ユーザーごとの注文データを集約するデータマート」の開発でした。

要件としては、「すべてのユーザーを起点に、注文があればその詳細も含めて集計する」こと。
SQLはそれなりに書けるようになってきたし、簡単そうだと思っていました。

SELECT u.id, u.name, o.status
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.status = 'completed'

このSQLで「完了した注文」だけを対象にして、各ユーザーの注文数を集計していったのですが…


⚠️ 問題が発覚したのは「総合テスト」

いざデータマートを結合し、総合テストで全体の数値検証をしていたとき
先輩が出したチェックリストと僕が作った集計表に微妙な差異がありました。

「ねえ、ユーザー数、ちょっと少なくない?」
「注文してないユーザーも含めるんじゃなかったっけ?」

血の気が引きました。
確かに、注文が「未完了」や「存在しない」ユーザーが集計からごっそり抜けていたのです。

原因は、結合条件の書き方。

-- NGパターン
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.status = 'completed'

LEFT JOINしてるつもりが、WHEREで条件をかけていたせいで、
ordersにマッチしないユーザー(未注文や未完了)は全員落ちていたんです。


✅ 正解はこう書くべきだった

-- OKパターン
LEFT JOIN orders o 
  ON u.id = o.user_id AND o.status = 'completed'

この書き方なら、「ユーザーは全員残しつつ、注文が完了しているものだけを結合」できます。
**「WHEREはフィルタ」「JOIN ... ONは結合ロジック」**という基本を、恥ずかしながら見落としていました。


🧠 教訓

  • SQLでは**「処理順序」を理解するのが超重要**
  • LEFT JOINでデータを残したいときは、結合条件にフィルタを入れるべき
  • 総合テストで「差分を疑う姿勢」はプロジェクトを救う

たかが1行の違い。でも、データマートの数字がズレると、意思決定やレポート全体が崩れるリスクがある


補足

区分 結合条件
JOIN ... ON
抽出条件
WHERE
タイミング 結合時に使われる 結合に使われる
目的 「どの行を結合するか」を決める 「どの行を最終的に残すか」を決める
よく使う場面 INNER JOIN, LEFT JOINなど フィルタリング(例: 日付、ステータス)
間違えやすい点 抽出条件と混同しがち LEFT JOINと併用時、行が消える可能性あり
ON u.id = o.user_id AND o.status = 'completed' WHERE o.status = 'completed'(←LEFT JOINだとNGになることも)

Discussion