Print Friendly, PDF & Email

この記事では、弊社の新人エンジニア研修の参考にMySQLを解説します。

前回は、複数テーブルに対する検索を解説しました。

今回は、副問合せについて解説します。

副問合せ

あるSELECT文の結果を別のSQL文で利用することができます。

SQLの中にSQLを記述することになるため副問合せといいます。

単一行副問合せ

入れ子にして埋め込んだSELECT文の結果が1行を返す場合の副問合せを単一行副問合せといいます

単一行副問合せの構文

SELECT 列名1,列名2, ... FROM 表名1

WHERE 列名 = (SELECT 列名 FROM 表名2 WHERE 抽出条件);

※このとき表名1,2は同じでも可

※ 列名 の後ろには=以外にも単一行比較演算子(<, <=, >, >=, !=)が使用可

例えば、carsテーブルから価格がもっとも高い商品のレコードを表示するにはこうします。

SELECT 
    *
FROM
    cars
WHERE
    price = (SELECT 
            MAX(price)
        FROM
            cars);

結果

新人エンジニア研修

このときコツはまず、()の中の副問い合わせ部分を先に実行して結果を確認することです。

MySQL Workbenchを使っていると()の中のSQL文をドラッグして選択状態にすることで副問い合わせ部分だけを実行することができますので試してみてください。

例えば、carsテーブルから価格が平均以上の商品のレコードを表示するにはこうします。

SELECT 
    *
FROM
    cars
WHERE
    price >= (SELECT 
            AVG(price)
        FROM
            cars);

結果

新人エンジニア研修

複数テーブルを使った副問合せの例を紹介します。

salesテーブルから一番最近購入したcustomer_idを抽出し、customersテーブルからその顧客のレコードを抽出してみます。

複数行副問合せ

入れ子にして埋め込んだSELECT文の結果が複数行を返す場合の副問合せを複数行副問合せといいます。

複数行副問合せの構文

SELECT 列名1,列名2, ... FROM 表名1

WHERE 列名 IN (SELECT 列名 FROM 表名2 WHERE 抽出条件);

※このとき表名1,2は同じでも可

※ 列名 の後ろにはIN以外にもNOT INが使用可

salesテーブルからクーペ(car_idは2)を購入したことのある顧客のcustomer_idとcustomer_nameを抽出してみます。

SELECT 
    customer_id,customer_name
FROM
    customers
WHERE
    customer_id IN (SELECT 
            customer_id
        FROM
            sales
        WHERE
            car_id = 2);

結果

新人エンジニア研修

副問合せを使ったテクニック

ここからは新人エンジニア研修の時間が許す限り、副問合せを使ったテクニックをご紹介します。

2番目に年齢の高い顧客を抽出するにはどうしたら良いでしょうか?

以下の例では「香川嘉子」さんです。

新人エンジニア研修

副問合せを使うことで可能になります。

考え方はこうです。

1.まずいちばん年齢の高い人を抽出します。

新人エンジニア研修
SELECT min(customers_birthday) FROM sip_a.customers

2.1で抽出された人より若い人からなるテーブルに対していちばん年齢の高い人を抽出します。

新人エンジニア研修

副問合せを使わないSQL文は以下の通りです。このようにSQLの実行を2段階にしないと実現できません。

SELECT 
    MIN(customers_birthday)
FROM
    sip_a.customers
WHERE
    customers_birthday > ('1961-12-16');

副問合せを使って書けば以下の通りSQLを1回書くだけで実現することができます。

SELECT 
    MIN(customers_birthday)
FROM
    sip_a.customers
WHERE
    customers_birthday > (SELECT 
            MIN(customers_birthday)
        FROM
            sip_a.customers);

まとめ

□ あるSELECT文の結果を別のSQL文で利用することを副問合せという

□入れ子にして埋め込んだSELECT文の結果が1行を返す場合の副問合せを単一行副問合せという

□入れ子にして埋め込んだSELECT文の結果が複数行を返す場合の副問合せを複数行副問合せという

以上、複数テーブルに対する検索について見てきました。

次回はトランザクション等その他の操作について見ていきましょう。

データベース(MySQL)へ戻る