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

なお、レンタルサーバー選びで迷ったらこちらの記事で主要レンタルサーバーのプランと料金を比較していますので、是非参考にしてみてください。

データベース編に戻る

このページのトップに戻る