初心者〜中級者向けSQL問題集|実務で使える思考力が身につく練習問題と解答例
CONTENTS
「SQLが書けない」から抜け出せない理由は“練習の仕方”にある
「SQLの構文は理解したはずなのに、実務のクエリが書けない」
「SELECTやJOINは分かるが、問題になると手が止まる」
「DISTINCTを入れたら動いたけど、本当に正しいのか不安」
こうした悩みは、SQL初学者〜中級者の多くが一度は通る壁です。
SQLは読むだけでは身につかない技術です。
重要なのは、手を動かして“考え方ごと”練習すること。
この記事では、
- 初心者〜中級者がつまずきやすいポイントを踏まえた → 段階式SQL練習問題
- 実務で通用する → 要件分解・粒度設計・デバッグ思考
- DISTINCT・JOIN・NULLなど → 現場で事故りやすい論点の整理
を、同一データセットで一気通貫に解説します。
「SQL問題集をやり切った」と胸を張れる状態まで、この記事1本で到達できる構成です。
SQL問題集の正しい使い方|最短で伸びる人の学習ルール
解答を見る前にやるべきことは「日本語での要件分解」
SQL問題に取り組む際、いきなりクエリを書き始めるのはNGです。
まず以下を必ず日本語で言語化してください。
- 欲しい列は何か
- 1行は何単位か(生徒ごと/教科ごと など)
- 集計が必要か/不要か
例:
「30点以下を取った生徒名を重複なく出したい」
この時点で、
- 生徒単位で1行
- 点数はexam_results
- 名前はstudents
- JOINが必要
- 重複対策が必要
まで見えているのが理想です。
復習で必ずやるべき「別解づくり」
正解に辿り着いたら終わりではありません。
- DISTINCTを使わずGROUP BYで書けないか
- INNER JOINをLEFT JOINにしたら結果はどう変わるか
- NOT INではなくNOT EXISTSで書くとどうなるか
別解を1つ作るだけで、SQL力は段違いに定着します。
学習の進め方|基礎 → 集計 → 結合 → 応用
SQL学習は「難易度の高い問題」より
同じ題材で条件を少しずつ増やす方が圧倒的に効果的です。
- 基礎:SELECT / WHERE
- 集計:GROUP BY / HAVING
- 結合:JOIN(INNER / LEFT)
- 応用:サブクエリ / ウィンドウ関数 / 存在判定
本記事はこの流れに完全準拠しています。
練習用データ設計|SQL力が伸びる2テーブル構成
テーブル概要
- students:生徒マスタ(1人1行)
- exam_results:試験結果明細(1生徒×複数教科)
マスタ × 明細の典型構造のため、
- JOINの行数増加
- DISTINCTの必要性
- 集計粒度の設計
を自然に体感できます。
students(生徒)テーブル
| カラム | 説明 |
|---|---|
| id | 生徒ID(主キー) |
| name | 生徒名 |
| gender | 性別 |
exam_results(試験結果)テーブル
| カラム | 説明 |
|---|---|
| student_id | 生徒ID(外部キー) |
| subject | 教科 |
| score | 点数 |
(student_id, subject)の複合主キー想定です。
SQL実行環境|環境構築で止まらないために
ブラウザで使える学習ツール
- DB Fiddle
https://dbfiddle.uk/
Schema SQLにCREATE/INSERT、Query SQLにSELECTを書くことで即実行できます。
※ DBの種類(MySQL / PostgreSQL)は必ず確認してください。
SQL練習問題【基礎編】SELECT / WHERE
問題1:性別が「男」の生徒名一覧を表示
要件
- 出力:生徒名
- 条件:gender = '男'
解答例
SELECT name
FROM students
WHERE gender = '男';
問題2:30点以下を1教科でも取った生徒名(重複なし)
ポイント
- 点数はexam_results
- 名前はstudents
- JOINが必要
- 重複対策が必要
解答例
SELECT DISTINCT s.name
FROM students s
JOIN exam_results e ON s.id = e.student_id
WHERE e.score <= 30;
⇒ DISTINCTを入れた理由を必ず説明できるようにしてください。
SQL練習問題【集計編】GROUP BY / HAVING
問題3:性別ごとの最高得点
粒度:性別ごとに1行
SELECT s.gender, MAX(e.score) AS max_score
FROM students s
JOIN exam_results e ON s.id = e.student_id
GROUP BY s.gender;
問題4:平均点が50点以下の教科
SELECT subject, AVG(score) AS avg_score
FROM exam_results
GROUP BY subject
HAVING AVG(score) <= 50;
⇒ HAVINGを使う理由を説明できれば合格です。
SQL練習問題【結合編】JOINの本質を理解する
INNER JOIN と LEFT JOIN の違い
- INNER:両方に存在するデータのみ
- LEFT:左テーブルは必ず残る
LEFT JOIN+WHERE条件でNULL行が消える罠に注意してください。
問題:英語が30点以下の生徒名
SELECT DISTINCT s.name
FROM exam_results e
JOIN students s ON e.student_id = s.id
WHERE e.subject = '英語'
AND e.score <= 30;
SQL練習問題【応用編】サブクエリ・ウィンドウ関数
問題5:各行に教科平均点を併記
ウィンドウ関数版
SELECT
student_id,
subject,
score,
AVG(score) OVER (PARTITION BY subject) AS subject_avg_score
FROM exam_results;
問題6:理科の試験結果が存在しない生徒
NOT EXISTS(推奨)
SELECT s.name
FROM students s
WHERE NOT EXISTS (
SELECT 1
FROM exam_results e
WHERE e.student_id = s.id
AND e.subject = '理科'
);
⇒ NOT IN と NULL 問題は実務頻出です。
よくある失敗パターンと回避策
WHERE と HAVING の混同
- 行に対する条件 → WHERE
- 集計結果に対する条件 → HAVING
DISTINCTで誤魔化している
- 重複の原因を説明できないならNG
- 粒度設計を見直すのが本質的解決
JOIN条件の漏れ
- JOIN直後の件数を必ず確認
- 主キー × 外部キーで結合しているか声に出す
まとめ|SQL問題集は「思考訓練」である
SQL力は、
- 構文暗記
- 難問攻略
ではなく、
- 要件を日本語で分解する力
- 粒度・結合・NULLを疑う習慣
- 途中結果で検算する癖
で決まります。
この記事の問題集を同じデータで何周も回すことが、
実務で通用するSQL力への最短ルートです。
次にやるべきこと|実務SQLへステップアップするために
- 条件を変えて再挑戦する
- 列・テーブルを追加して拡張する
- 別データセットでも同じ思考が通用するか試す
ここまでできれば、SQLは「武器」になります。
採用メッセージ|SQLを“理解して使える”エンジニアへ
私たちは、
SQLをただ書ける人ではなく、
「なぜそのクエリになるのか」を説明できるエンジニアと
一緒に働きたいと考えています。
- データを正しく扱いたい
- ロジックでプロダクトを支えたい
- 技術を深く理解する文化のあるチームで成長したい
そんな想いを持つ方にとって、
当社の環境はきっとフィットするはずです。
この記事を「面白い」「もっと深掘りしたい」と感じた方は、
ぜひ私たちの採用情報も覗いてみてください。
学び続けるエンジニアと、次の挑戦を待っています。
学んだSQLを、実務で使えるスキルにしたい方へ
本記事ではSQLの基本的な考え方や使い方を解説しましたが、
「実務で使えるレベルまで身につけたい」と感じた方も多いのではないでしょうか。
SQLは、文法を理解するだけでなく、
- どんなデータ構造で使われるのか
- どんなクエリが現場で求められるのか
を意識して学ぶことで、実践力が大きく変わります。
そうした「実務を見据えたSQL学習」を進めたい方には、
完全無料で学べるプログラミングスクール ZeroCode という選択肢もあります。
- SQLを含むWeb・データベース系スキルを体系的に学べる
- 未経験者でも実務を意識したカリキュラム
- 受講料・教材費がかからない完全無料の学習環境
- 完全オンラインでスキマ学習
※学習内容や進め方を確認するだけでもOKです