nikkie-ftnextの日記

イベントレポートや読書メモを発信

MySQLで2つのテーブルをJOINした条件で、片方のテーブルからDELETEする

公開日の学びではないのですが、Today I Learnedです。

目次

出発点:EXISTSと挫折結合を知った記事

2つのテーブルを扱いました。

  • Products
  • Order_Details

Order_Detailsにない(=注文されていない)Products(=製品)を一覧。
このクエリの書き方が挫折結合です。

SELECT
    p.ProductNumber,
    p.ProductName
FROM
    Products AS p
    LEFT JOIN Order_Details od on p.ProductNumber = od.ProductNumber
WHERE
    od.ProductNumber IS NULL;
+---------------+--------------------------------+
| ProductNumber | ProductName                    |
+---------------+--------------------------------+
|             4 | Victoria Pro All Weather Tires |
|            23 | Ultra-Pro Skateboard           |
+---------------+--------------------------------+
2 rows in set (0.01 sec)

こちらの挫折結合のクエリをベースに、条件に該当するレコードを片方のテーブルから削除していきます。

JOINした条件でDELETEする

(現実にはやらないと思いますが練習のための例として)Order_Detailsにない(=注文されていない)製品をProductsから消します。

挫折結合のクエリを以下のように書き換えます。

DELETE
    p
FROM
    Products AS p
    LEFT JOIN Order_Details od on p.ProductNumber = od.ProductNumber
WHERE
    od.ProductNumber IS NULL;

私にとっての学びは「DELETE p FROM」と、DELETEの直後にテーブル名のエイリアスが登場する点。
JOINを使わずに単一のテーブルから削除するとき、「DELETE FROM Products」じゃないですか

ドキュメントの「複数テーブル構文」より抜粋

DELETE
    tbl_name[.*] [, tbl_name[.*]] ...
    FROM table_references
    [WHERE where_condition]

同じドキュメントの「複数テーブルの削除」より

table_references 句は、結合に含まれるテーブルをリストします。

JOINを書くと、SQLの構文的にはtable_referencesに該当するわけですね

FROM 句の前にリストされているテーブルの一致する行のみが削除されます。

JOIN(table_reference)のうちのどのテーブルの行を削除するかを示すために、「DELETE p FROM」となると理解しました。

ProductsとOrder_Detailsに向けて流してみます。

-- 40
SELECT COUNT(1) FROM Products;

-- Productsのレコードを消せるように、外部キー制約を外す(今回は練習目的なので)
ALTER TABLE Product_Vendors DROP CONSTRAINT Product_Vendors_FK00;
-- 2件ともある
SELECT * FROM Products WHERE ProductNumber IN (4, 23);

DELETE
    p
FROM
    Products AS p
    LEFT JOIN Order_Details od on p.ProductNumber = od.ProductNumber
WHERE
    od.ProductNumber IS NULL;

-- Empty set
SELECT * FROM Products WHERE ProductNumber IN (4, 23);
-- 38
SELECT COUNT(1) FROM Products;

終わりに

MySQLで2つのテーブルをJOINした条件で、片方のテーブルからDELETEするには、「DELETE エイリアス FROM」のように書くことを知りました

DELETE
    [消したいテーブルのJOINで使っているエイリアス]
FROM
    [JOINを書く。例に使ったのは挫折結合]
WHERE
    [条件];