限りでは、にstory_category
存在しない行を削除する必要がありますcategory
。
削除する行を特定するための元のクエリは次のとおりです。
SELECT *
FROM story_category
WHERE category_id NOT IN (
SELECT DISTINCT category.id
FROM category INNER JOIN
story_category ON category_id=category.id
);
元のテーブルNOT IN
であるサブクエリと組み合わせると、JOIN
不必要に複雑になります。これはnot exists
、相関サブクエリを使用して、より簡単な方法で表現できます。
select sc.*
from story_category sc
where not exists (select 1 from category c where c.id = sc.category_id);
これをdelete
ステートメントに変えるのは簡単です:
delete from story_category
where not exists (select 1 from category c where c.id = story_category.category_id);
このクエリは、MySQLのどのバージョンでも、私が知っている他のほとんどのデータベースでも実行できます。
DB Fiddleのデモ:
-- set-up
create table story_category(category_id int);
create table category (id int);
insert into story_category values (1), (2), (3), (4), (5);
insert into category values (4), (5), (6), (7);
-- your original query to identify offending rows
SELECT *
FROM story_category
WHERE category_id NOT IN (
SELECT DISTINCT category.id
FROM category INNER JOIN
story_category ON category_id=category.id);
| category_id |
| ----------:|
| 1 |
| 2 |
| 3 |
-- a functionally-equivalent, simpler query for this
select sc.*
from story_category sc
where not exists (select 1 from category c where c.id = sc.category_id)
| category_id |
| ----------:|
| 1 |
| 2 |
| 3 |
-- the delete query
delete from story_category
where not exists (select 1 from category c where c.id = story_category.category_id);
-- outcome
select * from story_category;
| category_id |
| ----------:|
| 4 |
| 5 |