よくあるSQLのミスと対処
初学者がやりがちなSQLのミスを、原因と対処法つきでまとめます。NULLの比較、GROUP BYの列指定、暗黙の型変換、JOINでの行の重複など、つまずきやすいポイントを一覧で整理します。
SQL は書けるようになっても、思った結果にならないことがあります。その多くは「よくあるパターン」に当てはまります。ここでは初学者がつまずきやすいミスを、原因と対処つきで整理します。一度知っておくと、同じ失敗を避けられます。
1. NULL を = で比較してしまう
WHERE phone = NULL -- 一件も返らないNULL との = 比較は結果が「不明」になり、条件を満たしません。IS NULL / IS NOT NULL を使います。
WHERE phone IS NULL2. NOT IN とサブクエリの NULL
NOT IN のサブクエリ結果に NULL が混ざると、何も返らないことがあります。
WHERE id NOT IN (SELECT customer_id FROM orders) -- orders に NULL があると危険customer_id に NULL が含まれると、SQL の論理上すべての比較が「不明」になり、結果が空になります。安全なのは NOT EXISTS を使うことです。
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = customers.id
)3. GROUP BY に列を書き忘れる
集約と一緒に、集約していない列を SELECT に書くとエラーになります。
SELECT dept, name, AVG(salary) -- name が問題
FROM employees
GROUP BY dept;GROUP BY dept でまとめると、1 つの部門に複数の name があり、どれを返すか決まりません。SELECT に出せるのは GROUP BY の列か集約関数だけです。name を出したいなら、そもそも集約が適切かを見直します。
4. 集約関数を WHERE に書く
WHERE COUNT(*) > 1 -- エラー集約結果で絞りたいときは WHERE ではなく HAVING を使います(集約は WHERE より後に評価されるため)。
GROUP BY customer_id
HAVING COUNT(*) > 15. JOIN で行が意図せず増える
JOIN した結果、行数が想定より増えることがあります。これは結合先に該当行が複数あるためです。たとえば 1 件の注文に複数の明細があると、注文 × 明細の数だけ行が生成されます。
対処は、(a) 何を 1 行としたいかを明確にする、(b) 必要なら集約(GROUP BY + SUM など)でまとめる、です。「JOIN したら件数が合わない」と感じたら、結合の粒度を疑いましょう。
6. 整数どうしの割り算
SELECT 5 / 2; -- 2(小数点以下が切り捨て)整数どうしの割り算は、小数点以下が切り捨てられることがあります。小数で欲しいときは、どちらかを小数にします。
SELECT 5.0 / 2; -- 2.5
SELECT CAST(5 AS numeric) / 2;7. 文字列の大文字・小文字
WHERE name = 'alice' は、データが 'Alice' だと一致しません(多くのデータベースは既定で大文字小文字を区別します)。大小を無視して比較したいときは、両辺を揃えます。
WHERE LOWER(name) = 'alice'まとめ
よくあるミスは、たいてい次のどれかに根ざしています。
- NULL の特殊な振る舞い(比較・NOT IN)
- 集約のルール(GROUP BY の列、WHERE と HAVING)
- JOIN の粒度(行の増加)
- 型の扱い(整数割り算、大文字小文字)
「思った結果にならない」ときは、この一覧に当てはまっていないか確認してみてください。原因が分かれば、対処はシンプルです。