【初心者向け】SQLのUNION句とWHERE句を使いこなしてクエリをマスターしよう
SQLにおけるUNION後のWHEREステートメント
SQLのUNION句は、2つ以上のSELECTステートメントの結果セットを結合するために使用されます。各SELECTステートメントは独立したクエリであり、独自の列と行を持つことができます。UNION句を使用する場合は、結合される列の順序とデータ型が一致している必要があります。
WHEREステートメントの配置
WHEREステートメントは、UNION句の前後に配置できます。
各SELECTステートメントにWHEREステートメントを配置
この方法では、各SELECTステートメントで個別に結果をフィルタリングできます。最終的な結果セットは、各SELECTステートメントでフィルタリングされた行の結合となります。
-- 顧客テーブルと注文テーブルから顧客情報を取得
SELECT customer_id, name
FROM customers
WHERE active = 1
UNION
SELECT customer_id, name
FROM orders
WHERE order_status = 'shipped';
UNION句の後にWHEREステートメントを配置
この方法では、UNION句で結合されたすべての行に対して、単一のWHEREステートメントでフィルタリングを行います。
-- 顧客テーブルと注文テーブルから顧客情報を取得し、アクティブな顧客のみを表示
SELECT customer_id, name
FROM customers
WHERE active = 1
UNION
SELECT customer_id, name
FROM orders
WHERE order_status = 'shipped';
WHERE active = 1;
どちらの方法を選択するべきか?
それぞれの方法には利点と欠点があります。
- 欠点:
- 利点:
- 欠点:
- 利点:
適切な方法を選択
- シンプルで読みやすいクエリが必要な場合は、UNION句の後にWHEREステートメントを配置します。
- 結果セットに対してよりきめ細かな制御が必要な場合は、各SELECTステートメントにWHEREステートメントを配置します。
- WHEREステートメント以外にも、ORDER BYやLIMIT句などの句をUNION句と一緒に使用することができます。
- UNION句の代わりにINTERSECT句を使用することもできます。INTERSECT句は、2つのSELECTステートメントで一致する行のみを返します。
顧客情報と注文情報の取得
この例では、顧客テーブルと注文テーブルから顧客情報を取得し、以下の条件を満たすレコードのみを出力します。
- 注文は発送済みであること
- 顧客はアクティブであること
テーブル構造
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
active BOOLEAN NOT NULL
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT NOT NULL,
order_status VARCHAR(255) NOT NULL,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
データ
INSERT INTO customers (customer_id, name, active)
VALUES
(1, '田中 太郎', 1),
(2, '佐藤 花子', 0),
(3, '鈴木 次郎', 1);
INSERT INTO orders (order_id, customer_id, order_status)
VALUES
(1, 1, 'shipped'),
(2, 2, 'pending'),
(3, 1, 'shipped'),
(4, 3, 'shipped');
クエリ
-- 顧客テーブルと注文テーブルから顧客情報を取得し、アクティブな顧客と発送済み注文のみを表示
SELECT customer_id, name
FROM customers
WHERE active = 1
UNION
SELECT customer_id, name
FROM orders
WHERE order_status = 'shipped';
WHERE active = 1;
結果
customer_id | name
-----------+--------
1 | 田中 太郎
3 | 鈴木 次郎
解説
- 最初のSELECTステートメントは、
customers
テーブルからactive = 1
である顧客のcustomer_id
とname
列を選択します。 - 2番目のSELECTステートメントは、
orders
テーブルからorder_status = 'shipped'
である注文に関連付けられている顧客のcustomer_id
とname
列を選択します。 - UNION句は、2つのSELECTステートメントの結果セットを結合します。
- 最後のWHEREステートメントは、結合された結果セットから
active = 1
である顧客のみをフィルタリングします。
この例では、WHEREステートメント
を UNION句
の後に配置することで、customers
テーブルと orders
テーブルから取得したすべてのレコードをフィルタリングするのではなく、active = 1
である顧客と order_status = 'shipped'
である注文に関連付けられている顧客のみを抽出しています。
ORDER BY
句を使用して、結果セットをソートすることもできます。- 複数の条件でフィルタリングする場合は、
WHEREステートメント
にAND
句またはOR
句を使用することができます。 - 上記の例は、
WHEREステートメント
をUNION句
の前に配置した場合の書き換えも可能です。
ここでは、サブクエリを使用してWHEREステートメントを配置する方法について説明します。
サブクエリを使用したWHEREステートメントの配置
サブクエリを使用してWHEREステートメントを配置する方法では、UNION句を使用せずに、IN句またはEXISTS句を使用して、条件に合致するレコードのみを抽出します。
IN句を使用した方法
例: 顧客テーブルと注文テーブルから、注文ステータスが「shipped」または「pending」である顧客情報を取得する
-- 顧客テーブルと注文テーブルから顧客情報を取得
SELECT customer_id, name
FROM customers
WHERE customer_id IN (
SELECT customer_id
FROM orders
WHERE order_status IN ('shipped', 'pending')
);
- 内側のサブクエリは、
orders
テーブルからorder_status
が'shipped'
または'pending'
である注文に関連付けられているcustomer_id
をすべて選択します。 IN句
は、外側のSELECTステートメントのcustomer_id
列が、内側のサブクエリで選択されたcustomer_id
のいずれかの値と一致するかどうかを確認します。
EXISTS句を使用した方法
例: 顧客テーブルと注文テーブルから、注文履歴がある顧客情報を取得する
-- 顧客テーブルと注文テーブルから顧客情報を取得
SELECT customer_id, name
FROM customers
WHERE EXISTS (
SELECT 1
FROM orders
WHERE customer_id = customers.customer_id
);
- 内側のサブクエリは、
orders
テーブルでcustomer_id
が外側のSELECTステートメントのcustomer_id
と一致するレコードが存在するかどうかを確認します。 EXISTS句
は、内側のサブクエリが1行以上返したかどうかを確認します。1行以上返された場合、外側のSELECTステートメントはその顧客レコードを含みます。
メリットとデメリット
- デメリット:
- メリット:
- シンプルで分かりやすい構文
- デメリット:
- IN句と比べて構文が少し複雑
- メリット:
- リストが長い場合や、パフォーマンスが重要な場合は、EXISTS句を使用する方が良いでしょう。
- リストが短い場合は、IN句を使用する方がシンプルで読みやすいです。
- どの方法を選択する場合も、状況に応じて最適な方法を選択することが重要です。
- サブクエリ以外にも、
JOIN
句を使用して条件に合致するレコードのみを抽出する方法もあります。
mysql sql