サブクエリ(副問合せ)

ここではサブクエリ(副問合せ)について学習します。サブクエリとはSQLの中で利用する小さな select 文のことです。これから学習していくようにサブクエリでは select 文だけでなく、insert 文、 update 文、 delete 文でも利用できます。まずは select 文の中で利用するサブクエリについて確認していきましょう。

select 文の中で利用するサブクエリは from 句や、where 句、select 句などさまざまな場所で利用できます。

サブクエリ - from

サブクエリは select 文の from 句で利用できます。この場合はサブクエリによって取得_した結果に対して、select 文を実行することになります。次のSQLはサブクエリによって courses テーブルから category_id1 のレコードを取得しています。このサブクエリの結果(courses_1)に対して、 select 文 で id 列と title 列を取得しています。

MariaDB [eldb]> select id, title from 
    ->          (select id, title, learning_time from 
    ->           courses where category_id = 1) courses_1;
+----+--------------+
| id | title        |
+----+--------------+
|  1 | PHP Basic    |
|  2 | PHP Database |
|  3 | Python Basic |
+----+--------------+
3 rows in set (0.00 sec)

MariaDB [eldb]> 

上記のSQLの courses_1 という名前はサブクエリで取得した結果表に対する別名(エイリアス)です。またSQLの実行結果は、 select id, title from courses where category_id = 1; と同じになります。

サブクエリ - where

サブクエリは select 文の where 句でも利用できます。この場合はサブクエリの実行結果を where 句の条件に利用できます。次のSQLはサブクエリによって courses テーブルから category_time の最大値を取得しています。このサブクエリの結果を大元の select 文の where 句にて courses テーブルの learning_time 列と比較しています。

MariaDB [eldb]> select * from courses where learning_time =
    ->          (select max(learning_time) from courses);
+----+-----------------+---------------+-------------+
| id | title           | learning_time | category_id |
+----+-----------------+---------------+-------------+
|  5 | Japan's History |           100 |        NULL |
+----+-----------------+---------------+-------------+
1 row in set (0.00 sec)

MariaDB [eldb]> 

courses テーブルの中で learning_time の最大値を持つレコードを出力しています。

サブクエリ - select

サブクエリは select 文の select 句でも利用できます。この場合はサブクエリの実行結果を 大元の select 文の検索結果に追加できます。次のSQLはサブクエリによって courses テーブルから category_time の最大値を取得しています。このサブクエリの結果を大元の select 文の 検索結果に max_time 列として追加しています。

MariaDB [eldb]> select id, title, learning_time, 
    ->          (select max(learning_time) from courses) max_time from courses;
+----+-----------------+---------------+----------+
| id | title           | learning_time | max_time |
+----+-----------------+---------------+----------+
|  1 | PHP Basic       |            30 |      100 |
|  2 | PHP Database    |            50 |      100 |
|  3 | Python Basic    |            40 |      100 |
|  4 | Web Design      |            50 |      100 |
|  5 | Japan's History |           100 |      100 |
+----+-----------------+---------------+----------+
5 rows in set (0.00 sec)

MariaDB [eldb]> 

検索結果に learning_time の最大値を出力しています。

サブクエリ - delete

サブクエリは select 文以外のSQLでも利用できます。ここでは delete 文にサブクエリを適用する方法を見てみましょう。次のSQLはサブクエリによって categories テーブルから id 列の最小値を取得しています。 それから delete 文の where 句において、サブクエリで取得した id の最小値を使って条件式を定義しています。

MariaDB [eldb]> delete from courses 
    ->          where category_id = (select min(id) from categories);
Query OK, 3 rows affected (0.01 sec)

MariaDB [eldb]> select * from courses;
+----+-----------------+---------------+-------------+
| id | title           | learning_time | category_id |
+----+-----------------+---------------+-------------+
|  4 | Web Design      |            50 |           2 |
|  5 | Japan's History |           100 |        NULL |
+----+-----------------+---------------+-------------+
2 rows in set (0.00 sec)

MariaDB [eldb]>

category_id1 のレコードが削除されているのがわかります。

(補足)データの再登録

以降の講義を進めるために以下の insert 文を使って削除した3件のレコードを再登録しておきます。

insert into courses (id, title, learning_time, category_id) values (1, 'PHP Basic', 30, 1);
insert into courses (id, title, learning_time, category_id) values (2, 'PHP Database', 50, 1);
insert into courses (id, title, learning_time, category_id) values (3, 'Python Basic', 40,  1);

MySQLのクライアントプログラムを起動してSQLを実行してみましょう。

MariaDB [eldb]> insert into courses (id, title, learning_time, category_id) values (1, 'PHP Basic', 30, 1);
Query OK, 1 row affected (0.00 sec)

MariaDB [eldb]> insert into courses (id, title, learning_time, category_id) values (2, 'PHP Database', 50, 1);
Query OK, 1 row affected (0.00 sec)

MariaDB [eldb]> insert into courses (id, title, learning_time, category_id) values (3, 'Python Basic', 40,  1);
Query OK, 1 row affected (0.01 sec)

MariaDB [eldb]> 

それから 次の select 文を実行して5件のレコードが出力されることを確認します。

MariaDB [eldb]> select * from courses;
+----+-----------------+---------------+-------------+
| id | title           | learning_time | category_id |
+----+-----------------+---------------+-------------+
|  1 | PHP Basic       |            30 |           1 |
|  2 | PHP Database    |            50 |           1 |
|  3 | Python Basic    |            40 |           1 |
|  4 | Web Design      |            50 |           2 |
|  5 | Japan's History |           100 |        NULL |
+----+-----------------+---------------+-------------+
5 rows in set (0.00 sec)

MariaDB [eldb]>