サブクエリ 別のSQLクエリ内にネストされたSQL(構造化クエリ言語)クエリです。サブクエリがネストされているコマンドは、親クエリと呼ばれます。サブクエリは、親クエリで使用されるデータを前処理するために使用されます。サブクエリはSELECT
で適用できます 、INSERT
、UPDATE
、およびDELETE
操作。
サブクエリが実行されると、サブクエリは親クエリの前に最初に処理されます。 MySQLアプリケーションを構築する場合、サブクエリを使用するといくつかの利点があります。
- SQLステートメントを単純な論理ユニットに分割します。これにより、SQLステートメントの理解と保守が容易になります。つまり、サブクエリはクエリの複雑な部分を分離するのに役立ちます。
- 複雑な
UNION
を使用する必要がなくなります ステートメントとJOIN
ステートメント。 - 外部キーが実装されていないシナリオで参照の整合性を強制するために使用されます。
- 開発者がビジネスロジックをMySQLクエリにコーディングするのに役立ちます。
このガイドでは、次のことを学びます。
- 相関サブクエリの使用方法
- 比較演算子で相関サブクエリを使用する方法
- サブクエリを派生テーブルとして使用する方法
始める前に
このガイドに従うには、次のものがあることを確認してください。
-
まだ行っていない場合は、Linodeアカウントとコンピュートインスタンスを作成します。 Linode入門とコンピューティングインスタンスの作成ガイドをご覧ください。
-
コンピューティングインスタンスのセットアップと保護ガイドに従って、システムを更新してください。また、タイムゾーンを設定し、ホスト名を構成し、制限付きユーザーアカウントを作成し、SSHアクセスを強化することもできます。
-
LinodeにインストールされているMySQLサーバーソフトウェア(またはMariaDB)。いくつかのLinuxディストリビューションにMySQLをインストールする方法を説明するガイドが含まれているMySQLセクションを参照してください。
データベースのセットアップ
サブクエリがどのように機能するかを理解するには、最初にサンプルデータベースを作成します。このサンプルデータベースは、このガイドのさまざまなサンプルクエリを実行するために使用されます。
-
SSH
サーバーにアクセスし、rootとしてMySQLにログインします:mysql -u root -p
プロンプトが表示されたら、MySQLサーバーのrootパスワードを入力し、 Enterを押します。 続ける。 MySQLサーバーのルートパスワードはLinodeのルートパスワードと同じではないことに注意してください。
注 パスワードが受け入れられない場合は、
sudo
を使用して前のコマンドを実行する必要がある場合があります :sudo mysql -u root -p
-
パスワードが受け入れられると、MySQLプロンプトが表示されます:
mysql >
注 MariaDBを使用している場合は、代わりに次のようなプロンプトが表示される場合があります。
MariaDB [(none)]>
-
test_db
という名前のサンプルデータベースを作成するには 、実行:CREATE DATABASE test_db;
データベースが正常に作成されたことを確認する次の出力が表示されます。
Query OK, 1 row affected (0.01 sec)
-
test_db
に切り替えます データベース:USE test_db;
次の出力が表示されます:
Database changed
-
test_db
を作成しました そしてそれを選択しました。次に、customers
という名前のテーブルを作成します :CREATE TABLE customers ( customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;
次の出力が表示されます:
Query OK, 0 rows affected (0.03 sec)
-
customers
にいくつかのレコードを追加します テーブル。以下のINSERT
を実行します コマンドを1つずつ:INSERT INTO customers(customer_name) VALUES ('JOHN PAUL'); INSERT INTO customers(customer_name) VALUES ('PETER DOE'); INSERT INTO customers(customer_name) VALUES ('MARY DOE'); INSERT INTO customers(customer_name) VALUES ('CHRISTINE JAMES'); INSERT INTO customers(customer_name) VALUES ('MARK WELL'); INSERT INTO customers(customer_name) VALUES ('FRANK BRIAN');
この出力は、各レコードが挿入された後に表示されます:
Query OK, 1 row affected (0.00 sec) ...
-
顧客の情報がデータベースに挿入されたことを確認します。この
SELECT
を実行します コマンド:SELECT * FROM customers;
次の顧客リストが表示されます:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 3 | MARY DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | | 6 | FRANK BRIAN | +-------------+-----------------+ 6 rows in set (0.00 sec)
-
sales
を作成します テーブル。このテーブルでは、列customer_id
を使用していますcustomers
を参照するには テーブル:CREATE TABLE sales ( order_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_id BIGINT, sales_amount DECIMAL(17,2) ) ENGINE = InnoDB;
この出力が表示されます:
Query OK, 0 rows affected (0.03 sec)
-
次に、
sales
にデータを入力します いくつかのレコードを持つテーブル。以下のINSERT
を実行します コマンドを1つずつ:INSERT INTO sales (customer_id, sales_amount) VALUES ('1','25.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','85.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','3.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','200.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','88.10'); INSERT INTO sales (customer_id, sales_amount) VALUES ('1','100.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','45.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','15.80');
この出力は、各レコードが挿入された後に表示されます:
Query OK, 1 row affected (0.01 sec) ...
-
sales
のデータを確認します テーブル。このSELECT
を実行します コマンド:SELECT * FROM sales;
この販売データのリストが表示されます:
+----------+-------------+--------------+ | order_id | customer_id | sales_amount | +----------+-------------+--------------+ | 1 | 1 | 25.75 | | 2 | 2 | 85.25 | | 3 | 5 | 3.25 | | 4 | 4 | 200.75 | | 5 | 5 | 88.10 | | 6 | 1 | 100.00 | | 7 | 2 | 45.00 | | 8 | 4 | 15.80 | +----------+-------------+--------------+ 8 rows in set (0.00 sec)
データベースと関連テーブルを設定した後、MySQLでさまざまなサブクエリを実装できるようになりました。
相関サブクエリの使用方法
相関サブクエリは、親クエリの値を使用するネストされたクエリの一種です。これらの種類のクエリは、列を持つ親クエリを参照します。ネストされたクエリは、親クエリの行ごとに1回実行されます。
以下の例は、すべての顧客を選択するクエリを示しています。クエリ内には、sales
から各顧客の合計売上高を取得する相関サブクエリがあります。 テーブル。
-
クエリ例を実行します:
SELECT customer_id, customer_name, (SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id) as total_sales_amount FROM customers;
この例では、サブクエリは
SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id
です。 、括弧内に表示されます。顧客の総売上高のリストが表示されます:
+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | NULL | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | NULL | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
相関サブクエリからの上記の出力は、顧客の注文の要約リストを提供することができます。
customer_id
なので、注意してください ■3
および6
salesテーブルに関連するレコードがありません。それらのtotal_sales_amount
NULL
です 。 -
このリストを表示するためのより洗練された方法は、
0
を返すことです。NULL
の代わりに 売上がゼロのお客様向け。これを行うには、サブクエリによって生成された出力をIFNULL(expression, 0)
で囲みます。 声明。この更新されたコマンドを実行します:SELECT customer_id, customer_name, IFNULL((SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id), 0) as total_sales_amount FROM customers;
次の出力が表示されます。 MySQLは、そうでなければ
NULL
を返したはずのすべての行に対して0.00を返します。 値。+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | 0.00 | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | 0.00 | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
このアプローチは、出力がレコードのそれ以上の計算に悪影響を与えないようにするのに役立ちます。
比較演算子で相関サブクエリを使用する方法
サブクエリは、ビジネスロジックをデータベースクエリレベルに移動するのに役立ちます。次のビジネスユースケースは、親クエリのWHERE句内に配置された相関サブクエリを特徴としています。
-
データベースに登録されている、売上が関連付けられていないすべての顧客のリストを取得したいシナリオを考えてみます。サブクエリは、MySQL比較演算子
NOT IN
と一緒に使用できます。 これらの顧客を取得します:SELECT customer_id, customer_name FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
この例では、サブクエリは
SELECT customer_id FROM sales
です。 、括弧内に表示されます。上記のSQLコマンドは、salesテーブルにない2つの顧客のリストを出力します。+-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 3 | MARY DOE | | 6 | FRANK BRIAN | +-------------+---------------+ 2 rows in set (0.00 sec)
実稼働環境では、この種のレコードセットを使用して、より適切なビジネス上の意思決定を行うことができます。たとえば、PHPやPythonなどの別の言語を使用してスクリプトを作成し、これらの顧客にメールを送信して、注文に問題があるかどうかを問い合わせることができます。
-
もう1つのユースケースは、データのクリーンアップです。たとえば、サブクエリを使用して、注文したことのない顧客を削除できます。
DELETE FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
上記のSQLコマンドは、2つの顧客を削除し、以下を出力します。
Query OK, 2 rows affected (0.01 sec)
コマンドを実行してすべての顧客を再度一覧表示すると、これらの顧客はテーブルに表示されなくなります。
SELECT * FROM customers;
以下の出力は、関連する注文のない顧客が削除されたことを確認します。
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | +-------------+-----------------+ 4 rows in set (0.00 sec)
サブクエリを派生テーブルとして使用する方法
FROM
でサブクエリが使用されている場合 親クエリの句。派生テーブルと呼ばれます。 。これらは、MySQL VIEW
を必要とする複雑なクエリを実装する場合に非常に重要です。 、JOIN
、またはUNION
句。派生テーブルは、それを作成したクエリに存在し、データベースに永続的に保存されません。
サブクエリを派生テーブルとして使用する場合、サブクエリはSQLステートメントのさまざまな部分を分離します。つまり、サブクエリは、親クエリのスコープ内で使用できるテーブルの簡略化された式を提供します。
注 すべての派生テーブルはエイリアス化する必要があることを忘れないでください。
以下のコマンドを実行して、order_summary
としてエイリアスされる派生テーブルサブクエリを作成します :
SELECT customer_id
FROM
(
SELECT
customer_id,
count(order_id) as total_orders
FROM sales
group by customer_id
) as order_summary
WHERE order_summary.total_orders > 1;
注 このコマンドでは、サブクエリは括弧内に次のように表示されます。
SELECT customer_id, count(order_id) as total_orders FROM sales group by customer_id
上記のコマンドは、salesテーブルにクエリを実行して、複数の注文がある顧客を特定します。クエリを実行すると、次の出力が表示されます:
+-------------+
| customer_id |
+-------------+
| 1 |
| 2 |
| 5 |
| 4 |
+-------------+
4 rows in set (0.00 sec)
上記のリストは、4つのcustomer_id
を示しています。 s複数の注文がある。ビジネスのユースケースの例として、次の購入で顧客にボーナスを与えるスクリプトでこのようなクエリを使用できます。
詳細情報
このトピックの詳細については、次のリソースを参照してください。これらは有用であることを期待して提供されていますが、外部でホストされている資料の正確性や適時性を保証することはできません。
- MySQLサブクエリ