SQLiteにおけるFULL OUTER JOINとLEFT JOIN + RIGHT JOINの違い
SQLiteで完全外部結合を実行する方法
FULL OUTER JOIN を使用する方法
SELECT *
FROM テーブル1
FULL OUTER JOIN テーブル2
ON テーブル1.列名 = テーブル2.列名;
このクエリは、テーブル1とテーブル2のすべての行を返します。一致する行は結合され、一致しない行は NULL
値で表示されます。
例
-- 従業員テーブルと部門テーブル
CREATE TABLE 従業員 (
id INTEGER PRIMARY KEY,
名前 TEXT,
部門_id INTEGER
);
CREATE TABLE 部門 (
id INTEGER PRIMARY KEY,
名前 TEXT
);
-- データ挿入
INSERT INTO 従業員 (名前, 部門_id) VALUES ('田中', 1), ('佐藤', 2), ('斎藤', NULL);
INSERT INTO 部門 (名前) VALUES ('営業部', '開発部');
-- 完全外部結合
SELECT *
FROM 従業員
FULL OUTER JOIN 部門
ON 従業員.部門_id = 部門.id;
このクエリは、以下の結果を返します。
| id | 名前 | 部門_id | id | 名前 |
|---|---|---|---|---|
| 1 | 田中 | 1 | 1 | 営業部 |
| 2 | 佐藤 | 2 | 2 | 開発部 |
| 3 | 斎藤 | NULL | NULL | NULL |
LEFT JOIN と RIGHT JOIN を組み合わせる方法
-- 左外部結合
SELECT *
FROM テーブル1
LEFT JOIN テーブル2
ON テーブル1.列名 = テーブル2.列名;
-- 右外部結合
SELECT *
FROM テーブル1
RIGHT JOIN テーブル2
ON テーブル1.列名 = テーブル2.列名;
-- 結果を結合
SELECT *
FROM (
SELECT *
FROM 左外部結合
)
UNION
SELECT *
FROM 右外部結合
WHERE テーブル2.列名 IS NULL;
この方法は、LEFT JOIN
と RIGHT JOIN
を使用して、テーブル1とテーブル2のすべての行を個別に取得し、UNION
を使用して結果を結合します。WHERE
句は、右外部結合で取得された NULL
値のみをフィルタリングするために使用されます。
-- 上記の例と同じ
-- 左外部結合
SELECT *
FROM 従業員
LEFT JOIN 部門
ON 従業員.部門_id = 部門.id;
-- 右外部結合
SELECT *
FROM 従業員
RIGHT JOIN 部門
ON 従業員.部門_id = 部門.id;
-- 結果を結合
SELECT *
FROM (
SELECT *
FROM 左外部結合
)
UNION
SELECT *
FROM 右外部結合
WHERE 部門.id IS NULL;
このクエリは、上記の FULL OUTER JOIN
の例と同じ結果を返します。
どちらの方法を使用しても、同じ結果を取得できます。一般的には、FULL OUTER JOIN
の方が簡潔で読みやすいので、こちらの方が好まれることが多いです。
注意事項
- SQLiteバージョン3.39.0以降では、
FULL OUTER JOIN
が正式にサポートされています。 - それ以前のバージョンのSQLiteを使用している場合は、
LEFT JOIN
とRIGHT JOIN
を組み合わせる方法を使用する必要があります。
補足
- 上記の例では、
*
を使用してすべての列を選択していますが、必要な列のみを選択することもできます。 ON
句では、結合条件を指定します。複数の条件を指定する場合は、AND
またはOR
演算子を使用できます。WHERE
句は、結果をフィルタリングするために使用できます。
関連キーワード
- SQL
- SQLite
- JOIN
- LEFT JOIN
- RIGHT JOIN
- UNION
-- 従業員テーブルと部門テーブル
CREATE TABLE 従業員 (
id INTEGER PRIMARY KEY,
名前 TEXT,
部門_id INTEGER
);
CREATE TABLE 部門 (
id INTEGER PRIMARY KEY,
名前 TEXT
);
-- データ挿入
INSERT INTO 従業員 (名前, 部門_id) VALUES ('田中', 1), ('佐藤', 2), ('斎藤', NULL);
INSERT INTO 部門 (名前) VALUES ('営業部', '開発部');
-- 完全外部結合
SELECT *
FROM 従業員
FULL OUTER JOIN 部門
ON 従業員.部門_id = 部門.id;
結果
| id | 名前 | 部門_id | id | 名前 |
|---|---|---|---|---|
| 1 | 田中 | 1 | 1 | 営業部 |
| 2 | 佐藤 | 2 | 2 | 開発部 |
| 3 | 斎藤 | NULL | NULL | NULL |
-- 左外部結合
SELECT *
FROM 従業員
LEFT JOIN 部門
ON 従業員.部門_id = 部門.id;
-- 右外部結合
SELECT *
FROM 従業員
RIGHT JOIN 部門
ON 従業員.部門_id = 部門.id;
-- 結果を結合
SELECT *
FROM (
SELECT *
FROM 左外部結合
)
UNION
SELECT *
FROM 右外部結合
WHERE 部門.id IS NULL;
| id | 名前 | 部門_id | id | 名前 |
|---|---|---|---|---|
| 1 | 田中 | 1 | 1 | 営業部 |
| 2 | 佐藤 | 2 | 2 | 開発部 |
| 3 | 斎藤 | NULL | NULL | NULL |
SQLiteで完全外部結合を実行する他の方法
SELECT *
FROM テーブル1
WHERE EXISTS (
SELECT *
FROM テーブル2
WHERE テーブル1.列名 = テーブル2.列名
);
このクエリは、テーブル1のすべての行を返し、テーブル2に一致する行が存在するかどうかをチェックします。一致する行が存在する場合は、すべての列が返されます。一致する行が存在しない場合は、NULL
値が返されます。
-- 従業員テーブルと部門テーブル
CREATE TABLE 従業員 (
id INTEGER PRIMARY KEY,
名前 TEXT,
部門_id INTEGER
);
CREATE TABLE 部門 (
id INTEGER PRIMARY KEY,
名前 TEXT
);
-- データ挿入
INSERT INTO 従業員 (名前, 部門_id) VALUES ('田中', 1), ('佐藤', 2), ('斎藤', NULL);
INSERT INTO 部門 (名前) VALUES ('営業部', '開発部');
-- 完全外部結合
SELECT *
FROM 従業員
WHERE EXISTS (
SELECT *
FROM 部門
WHERE 従業員.部門_id = 部門.id
);
| id | 名前 | 部門_id |
|---|---|---|
| 1 | 田中 | 1 |
| 2 | 佐藤 | 2 |
| 3 | 斎藤 | NULL |
CASE 式を使用する方法
SELECT
従業員.id,
従業員.名前,
CASE
WHEN 部門.名前 IS NULL THEN '所属なし'
ELSE 部門.名前
END AS 部門名
FROM 従業員
LEFT JOIN 部門
ON 従業員.部門_id = 部門.id;
このクエリは、CASE
式を使用して、部門名を取得します。部門が存在する場合は、部門名が返されます。部門が存在しない場合は、「所属なし」という文字列が返されます。
-- 上記の例と同じ
-- 完全外部結合
SELECT
従業員.id,
従業員.名前,
CASE
WHEN 部門.名前 IS NULL THEN '所属なし'
ELSE 部門.名前
END AS 部門名
FROM 従業員
LEFT JOIN 部門
ON 従業員.部門_id = 部門.id;
| id | 名前 | 部門名 |
|---|---|---|
| 1 | 田中 | 営業部 |
| 2 | 佐藤 | 開発部 |
| 3 | 斎藤 | 所属なし |
FULL OUTER JOIN
は、最も簡潔で読みやすい方法です。EXISTS
キーワードは、テーブル2に存在する行のみを取得したい場合に役立ちます。CASE
式は、結合結果にカスタム列を追加したい場合に役立ちます。
注意事項
EXISTS
キーワードは、SQLiteバージョン3.8.0以降でサポートされています。CASE
式は、すべてのSQLiteバージョンでサポートされています。
関連キーワード
- EXISTS
- CASE
sql sqlite join