LoginSignup
52
49

More than 3 years have passed since last update.

SQL初心者〜中級者のための練習問題&解答例1

Last updated at Posted at 2020-11-21

SQL初心者〜中級者のための練習問題+解答例をいくつか作ってみました。
SQL力向上のためにお役立てください。

その2: SQL初心者〜中級者のための練習問題&解答例2
その3: SQL初心者〜中級者のための練習問題&解答例3

ツールの紹介

DB Fiddleを使うとブラウザ上で簡単にSQLを実行できます。
画面左側のSchema SQLにスキーマを、画面右側のQuery SQLにクエリ(SELECT句)を書いて、画面上部の「Run」ボタンを押すだけです。
環境構築要らないので便利です。

題材

学生テーブル

学籍番号 氏名 性別
0001 長岡 一馬
0002 中本 知佳
0003 松本 義文
0004 佐竹 友香

試験結果テーブル

学籍番号 教科 点数
0001 国語 30
0001 英語 30
0002 国語 70
0002 数学 80
0003 理科 92
0004 社会 90
0004 理科 35
0004 英語 22

Schema SQL
CREATE TABLE `students` (
  `id` int(4) unsigned zerofill NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` varchar(255) NOT NULL,
  `gender` varchar(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `students` (`id`, `name`, `gender`)
VALUES
    (0001, '長岡 一馬', '男'),
    (0002, '中本 知佳', '女'),
    (0003, '松本 義文', '男'),
    (0004, '佐竹 友香', '女');

CREATE TABLE `exam_results` (
  `student_id` int(4) unsigned zerofill NOT NULL,
  `subject` varchar(255) NOT NULL,
  `score` bigint(20) unsigned NOT NULL,
  PRIMARY KEY(`student_id`, `subject`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `exam_results` (`student_id`, `subject`, `score`)
VALUES
    (0001, '国語', 30),
    (0001, '英語', 30),
    (0002, '国語', 70),
    (0002, '数学', 80),
    (0003, '理科', 92),
    (0004, '社会', 90),
    (0004, '理科', 35),
    (0004, '英語', 22);

問1

性別が男である生徒の名前を一覧で表示せよ。

name
長岡 一馬
松本 義文

解答例
SELECT
    name
FROM
    students
WHERE
    gender = '男'

問2

1教科でも30点以下の点数を取った生徒の名前を一覧で表示せよ。
ただし、重複は許さないものとする。

name
長岡 一馬
佐竹 友香

解答例
SELECT DISTINCT
    s.name
FROM
    exam_results er
INNER JOIN students s
    ON er.student_id = s.id
WHERE
    er.score <= 30

問3

性別ごとに、最も高かった試験の点数を表示せよ。

gender max_score
92
90

解答例
SELECT
    s.gender,
    MAX(er.score) AS max_score
FROM
    students s
INNER JOIN exam_results er
    ON s.id = er.student_id
GROUP BY
    s.gender

問4

教科ごとの試験の平均点が50点以下である教科を表示せよ。

subject avg_score
国語 50.0000
英語 26.0000

解答例
SELECT
    subject,
    AVG(score) AS avg_score
FROM
    exam_results
GROUP BY
    subject
HAVING
    AVG(score) <= 50

問5

試験結果テーブルの点数の右に、その教科の平均点を表示せよ。

student_id subject score subject_avg_score
0001 国語 30 50.0000
0001 英語 30 26.0000
0002 国語 70 50.0000
0002 数学 80 80.0000
0003 理科 92 63.5000
0004 理科 35 63.5000
0004 社会 90 90.0000
0004 英語 22 26.0000

解答例1
SELECT
    er1.*,
    (
        SELECT
            AVG(er2.score)
        FROM
            exam_results er2
        WHERE
            er1.subject = er2.subject
    ) AS subject_avg_score
FROM
    exam_results er1

解答例2(提供: @takahasinaoki さん)
SELECT
    *,
    AVG(score) OVER(PARTITION BY subject) AS subject_avg_score
FROM
    exam_results
ORDER BY 
    student_id

※MySQL8.0以上でしか動きません

問6

試験結果に理科が含まれない生徒の名前を一覧で表示せよ。

name
長岡 一馬
中本 知佳

解答例1
SELECT
    s.name
FROM
    students s
INNER JOIN exam_results er
    ON s.id = er.student_id
GROUP BY
    s.id
HAVING
    SUM(CASE WHEN er.subject = '理科'  THEN 1 ELSE 0 END) = 0

解答例2(提供: @takahasinaoki さん)
SELECT
    name
FROM
    students
WHERE 
    id NOT IN (
        SELECT
            student_id
        FROM
            exam_results
        WHERE
            subject = '理科'
    )

解答例3(提供: @takahasinaoki さん)
SELECT
    name
FROM
    students s
WHERE 
    NOT EXISTS (
        SELECT
            *
        FROM
            exam_results
        WHERE
            subject = '理科'
            AND
            student_id = s.id
    )

52
49
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
49