SQLの副問合せとは?
カテゴリ:データベース編
副問合せは、問い合わせの中で他の問い合わせを行うことを意味します。つまりSELECT文やINSERT文の中でSELECT文を実行するということです。例えば、MySQLの制約と自動インクリメントではcategoryカラムを別テーブルに分け、外部キー制約を設定していますが、参照キーをcategoryではなくidにして、blogテーブルではcategoryをidで保持させる方が、データサイズが小さく済み、テーブルサイズやテーブル更新時の負荷を抑えられます。
具体的には、blogテーブルのcategory_idカラムがcategory_listテーブルのidを参照するように、以下のようにテーブルを作り変えます。(一旦blogデータベースを削除して再作成するか、別のデータベースを作成してください)
CREATE TABLE category_list (
id INT PRIMARY KEY AUTO_INCREMENT,
category VARCHAR(100) UNIQUE KEY NOT NULL
);
CREATE TABLE blog (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(100) NOT NULL,
text TEXT NOT NULL,
date DATETIME,
category_id INT NOT NULL,
FOREIGN KEY (category_id) REFERENCES category_list(id) ON DELETE RESTRICT ON UPDATE CASCADE
);
準備としてcategory_listテーブルにカテゴリー名を登録しておきます。
mysql> INSERT INTO category_list (id, category) VALUES ('1', 'データベース');
Query OK, 1 row affected (0.11 sec)
この場合、blogテーブルにレコードを挿入する際、カテゴリーはcategoryではなく、category_idで登録する必要があります。そのため、レコードの挿入時に以下のようにcategory_listに対してcategoryの値が「データベース」のidを取得し、そのidをcategory_idの値として渡すSELECT文を実行する事になります。
INSERT INTO blog (title, text, date, category_id) VALUES ('ブログ始めました', '今日はデータベースのお勉強をしました。', NOW(), (SELECT id FROM category_list WHERE category = 'データベース'));
実行後、blogテーブルの内容を見てみましょう。category_idは、idで登録されている事が確認できますね。
mysql> INSERT INTO blog (title, text, date, category_id) VALUES ('ブログ始めました', '今日はデータベースのお勉強をしました。', NOW(), (SELECT id FROM category_list WHERE category = 'データベース'));
Query OK, 1 row affected (0.10 sec)
mysql> SELECT id, category_id, title, text, date FROM blog WHERE id = 1;
+----+-------------+--------------------------+-----------------------------------------------------------+---------------------+
| id | category_id | title | text | date |
+----+-------------+--------------------------+-----------------------------------------------------------+---------------------+
| 1 | 1 | ブログ始めました | 今日はデータベースのお勉強をしました。 | 2020-05-03 17:36:46 |
+----+-------------+--------------------------+-----------------------------------------------------------+---------------------+
1 row in set (0.00 sec)
では、blogのレコードを抽出する際に、category_idではなく、category名で表示する場合はどうすればいいのでしょうか。その場合も、同様に副問合せで解決できます。 今度は、抽出するカラムを指定する箇所に、category_listテーブルからidに一致するカテゴリー名を取得するSELECT文を指定します。
SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, text, date FROM blog WHERE id = 1;
以下のように、今度はcategoryカラムにカテゴリー名で表示されていますね。
mysql> SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, text, date FROM blog WHERE id = 1;
+----+--------------------+--------------------------+-----------------------------------------------------------+---------------------+
| id | category | title | text | date |
+----+--------------------+--------------------------+-----------------------------------------------------------+---------------------+
| 1 | データベース | ブログ始めました | 今日はデータベースのお勉強をしました。 | 2020-05-03 17:36:46 |
+----+--------------------+--------------------------+-----------------------------------------------------------+---------------------+
1 row in set (0.00 sec)
参考ASはカラム名を別名を付ける際に使用します。AS categoryと指定すれば、カラム名にcategoryとして表示されます。
以上、副問合せについて解説いたしました。
公開日時:2020年05月03日 17:56:09