FULL OUTER JOIN、UNION、GROUP BY、HAVING句、ウィンドウ関数を使ったINNER JOINの逆結果の取得

2024-04-02

MariaDBにおけるINNER JOINの逆結果の取得方法

このチュートリアルでは、MariaDBにおけるINNER JOINの逆結果を取得する方法を、いくつかの方法で分かりやすく解説します。

目次

  1. NOT INを使用した方法
  2. EXISTSを使用した方法
  3. サブクエリを使用した方法

NOT INを使用した方法

NOT IN演算子は、ある列の値が別のテーブルの列の値に存在しないことを確認するために使用できます。

SELECT *
FROM table1
WHERE column1 NOT IN (
  SELECT column2
  FROM table2
);

この例では、table1column1の値がtable2column2の値に存在しないすべてのレコードが抽出されます。

LEFT JOINを使用した方法

LEFT JOINは、左側のテーブルのすべてのレコードを返し、右側のテーブルとの一致レコードがあれば追加で情報を取得します。

SELECT *
FROM table1
LEFT JOIN table2
ON table1.column1 = table2.column2
WHERE table2.column2 IS NULL;

この例では、table1のすべてのレコードが返され、table2との一致レコードがあればtable2の情報も取得されます。ただし、table2に一致するレコードがない場合は、column2はNULLになります。

EXISTSを使用した方法

EXISTSは、サブクエリが空でないかどうかを確認するために使用できます。

SELECT *
FROM table1
WHERE EXISTS (
  SELECT *
  FROM table2
  WHERE table1.column1 = table2.column2
);

この例では、table2table1column1と一致するレコードが存在するすべてのtable1のレコードが抽出されます。

CASE式を使用した方法

CASE式は、条件によって異なる値を返すことができます。

SELECT *
FROM table1
WHERE CASE
  WHEN column1 IN (
    SELECT column2
    FROM table2
  ) THEN '共通'
  ELSE '非共通'
END = '非共通';

この例では、table1column1table2column2に存在する場合は「共通」、そうでない場合は「非共通」という文字列が返されます。

サブクエリを使用して、INNER JOINの逆結果を取得することもできます。

SELECT *
FROM table1
WHERE table1.column1 NOT IN (
  SELECT column2
  FROM (
    SELECT *
    FROM table1
    INNER JOIN table2
    ON table1.column1 = table2.column2
  ) AS t
);

この例では、table1table2をINNER JOINした結果からcolumn2のみを抽出し、その値がtable1column1に存在しないレコードを抽出します。

上記のすべての方法を実演するサンプルコードを用意しました。

-- NOT IN
SELECT *
FROM customers
WHERE country NOT IN ('USA', 'Canada');

-- LEFT JOIN
SELECT *
FROM customers
LEFT JOIN orders
ON customers.id = orders.customer_id
WHERE orders.id IS NULL;

-- EXISTS
SELECT *
FROM customers
WHERE EXISTS (
  SELECT *
  FROM orders
  WHERE customers.id = orders.customer_id
);

-- CASE
SELECT *
FROM customers
WHERE CASE
  WHEN country IN ('USA', 'Canada') THEN 'North America'
  ELSE 'Other'
END = 'Other';

-- サブクエリ
SELECT *
FROM customers
WHERE customers.id NOT IN (
  SELECT customer_id
  FROM (
    SELECT *
    FROM customers
    INNER JOIN orders
    ON customers.id = orders.customer_id
  ) AS t
);

まとめ

MariaDBにおけるINNER JOINの逆結果を取得するには、さまざまな方法があります。




-- テーブル定義
CREATE TABLE customers (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  country VARCHAR(255) NOT NULL
);

CREATE TABLE orders (
  id INT PRIMARY KEY AUTO_INCREMENT,
  customer_id INT NOT NULL,
  order_date DATETIME NOT NULL,
  FOREIGN KEY (customer_id) REFERENCES customers (id)
);

-- データ挿入
INSERT INTO customers (name, country) VALUES
  ('John Doe', 'USA'),
  ('Jane Doe', 'Canada'),
  ('Peter Smith', 'UK'),
  ('Anna Smith', 'Germany');

INSERT INTO orders (customer_id, order_date) VALUES
  (1, '2023-01-01'),
  (1, '2023-02-01'),
  (2, '2023-03-01'),
  (3, '2023-04-01');

-- NOT IN
SELECT *
FROM customers
WHERE country NOT IN ('USA', 'Canada');

-- LEFT JOIN
SELECT *
FROM customers
LEFT JOIN orders
ON customers.id = orders.customer_id
WHERE orders.id IS NULL;

-- EXISTS
SELECT *
FROM customers
WHERE EXISTS (
  SELECT *
  FROM orders
  WHERE customers.id = orders.customer_id
);

-- CASE
SELECT *
FROM customers
WHERE CASE
  WHEN country IN ('USA', 'Canada') THEN 'North America'
  ELSE 'Other'
END = 'Other';

-- サブクエリ
SELECT *
FROM customers
WHERE customers.id NOT IN (
  SELECT customer_id
  FROM (
    SELECT *
    FROM customers
    INNER JOIN orders
    ON customers.id = orders.customer_id
  ) AS t
);

このコードを実行すると、以下の結果が出力されます。

-- NOT IN
+----+-------+---------+
| id | name  | country |
+----+-------+---------+
| 3  | Peter | UK      |
| 4  | Anna  | Germany |
+----+-------+---------+

-- LEFT JOIN
+----+-------+---------+------+------------+
| id | name  | country | id   | order_date |
+----+-------+---------+------+------------+
| 3  | Peter | UK      | NULL | NULL       |
| 4  | Anna  | Germany | NULL | NULL       |
+----+-------+---------+------+------------+

-- EXISTS
+----+-------+---------+
| id | name  | country |
+----+-------+---------+
| 3  | Peter | UK      |
| 4  | Anna  | Germany |
+----+-------+---------+

-- CASE
+----+-------+---------+---------+
| id | name  | country | region  |
+----+-------+---------+---------+
| 3  | Peter | UK      | Other   |
| 4  | Anna  | Germany | Other   |
+----+-------+---------+---------+

-- サブクエリ
+----+-------+---------+
| id | name  | country |
+----+-------+---------+
| 3  | Peter | UK      |
| 4  | Anna  | Germany |
+----+-------+---------+

必要に応じて、修正して使用してください。




MariaDBにおけるINNER JOINの逆結果を取得するその他の方法

以下に、いくつかの例を紹介します。

SELECT *
FROM table1
FULL OUTER JOIN table2
ON table1.column1 = table2.column2
WHERE table2.column2 IS NULL OR table1.column1 IS NULL;

UNIONは、複数のクエリ結果を結合するのに使用できます。

(
  SELECT *
  FROM table1
  WHERE column1 NOT IN (
    SELECT column2
    FROM table2
  )
)
UNION
(
  SELECT *
  FROM table2
  WHERE column2 NOT IN (
    SELECT column1
    FROM table1
  )
);

この例では、table1column1table2column2に存在しないレコードと、table2column2table1column1に存在しないレコードを抽出します。

GROUP BYを使用した方法

GROUP BYは、列の値に基づいてレコードをグループ化するのに使用できます。

SELECT *
FROM table1
GROUP BY column1
HAVING COUNT(DISTINCT column2) = 1;

この例では、table1column1に基づいてレコードをグループ化し、column2の値が1つだけのグループのみを抽出します。

HAVING句を使用した方法

HAVING句は、GROUP BYの結果に対して条件を指定するのに使用できます。

SELECT *
FROM table1
INNER JOIN table2
ON table1.column1 = table2.column2
GROUP BY table1.column1
HAVING COUNT(*) = 1;

この例では、table1table2をINNER JOINし、table1column1に基づいてレコードをグループ化します。そして、column1ごとに1つのレコードのみ存在するグループのみを抽出します。

ウィンドウ関数を使用した方法

ウィンドウ関数は、グループ内のレコードに対して計算を行うのに使用できます。

SELECT *
FROM (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2) AS rn
  FROM table1
) AS t
WHERE rn = 1;

この例では、table1column1に基づいてレコードをグループ化し、column2の値に基づいて各グループ内のレコードに順位を付けます。そして、各グループ内で順位が1番目のレコードのみを抽出します。

これらの方法は、それぞれ異なる方法でINNER JOINの逆結果を取得します。

状況に合わせて、最適な方法を選択してください。


mariadb


【初心者向け解説】MySQL、MariaDB、TokuDBで「GROUP BY WHERE range AND const ref without temporary」プログラミングをマスター!

この解説では、MySQL、MariaDB、TokuDBにおける「GROUP BY WHERE range AND const ref without temporary」プログラミングについて、詳細かつ分かりやすく説明します。概要「GROUP BY WHERE range AND const ref without temporary」は、データベーステーブルのレコードをグループ化し、特定の条件に基づいて集計を行うためのクエリ構文です。このクエリは、以下の3つの要素で構成されています。...


MariaDB alter table row format doesn't work の原因と解決策

MariaDBでALTER TABLEコマンドを使用してテーブルの行形式を変更しようとすると、エラーが発生することがあります。原因:この問題は、いくつかの要因が考えられます。innodb_file_formatの設定: innodb_file_formatがBARROWでない場合、ROW_FORMATを変更できません。...


Microsoft SQL Server と互換性のある UUID を生成: MariaDB 10.1 で NEWID() 関数を使う

UUID() 関数を使うMariaDB 10. 1 には、UUID() 関数が組み込まれています。 この関数は、バージョン 4 の UUID を生成します。利点:最もシンプルで、使いやすい方法です。標準の UUID バージョン 4 を生成します。...


さようなら、ログ収集ツール!DockerでMySQLログを直接/dev/stdoutへ出力する方法

方法1:コンテナをtty付きで実行するこのコマンドは、mysql-containerという名前のコンテナを起動し、/dev/stdoutにログを出力します。方法2:コンテナ内のユーザーをttyグループに追加するこのコマンドは、mysql-containerという名前のコンテナを起動し、コンテナ内のrootユーザーをttyグループに追加します。その後、以下のコマンドを実行してログを/dev/stdoutに出力できます。...


ROUND() 関数を使ってMariaDBの「I have an error in my SQL syntax when I convert the query from default floating-point to decimal point」エラーを解決

このエラーは、MariaDBで浮動小数点型データを固定小数点型データに変換するクエリを実行しようとしたときに発生します。MariaDBでは、デフォルトの浮動小数点型データは FLOAT または DOUBLE であり、固定小数点型データは DECIMAL または NUMERIC です。...


SQL SQL SQL SQL Amazon で見る



MariaDBでNATURAL JOINを使用して結合クエリを作成する方法

JOIN句を使用するJOIN句は、複数のテーブルを結合するための最も一般的な方法です。JOIN句には、結合の種類と結合条件を指定する必要があります。結合の種類INNER JOIN:両方のテーブルに一致するレコードのみを返します。LEFT JOIN:左側のテーブルのすべてのレコードを返し、右側のテーブルと一致するレコードがあればそれを返します。


MariaDBでサブクエリを極める!列化テクニックでデータ分析を自由自在に

最も簡単な方法は、SELECT 句でサブクエリを直接使用するものです。この方法では、サブクエリを括弧で囲み、SELECT 句の後にカンマ区切りで記述します。この例では、main_table テーブルから column1 と column2 列を抽出し、subquery_table テーブルから subquery_column 列をサブクエリとして取得し、subquery_column_alias という名前の列名で結果クエリに追加します。