私はこのようなクエリをしようとしています:
DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015
);
おそらくわかるように、同じtidに他の親がある場合、1015への親関係を削除します。しかし、それは私に構文エラーをもたらします:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS th
WHERE th.parent = 1015 AND th.tid IN (
SELECT DISTINCT(th1.tid)
FROM ter' at line 1
ドキュメントを確認し、サブクエリを単独で実行しましたが、すべてがチェックアウトされているようです。誰がここで何が間違っているのか理解できますか?
更新:以下で回答するように、MySQLは削除するテーブルを条件のサブクエリで使用することを許可しません。
削除するターゲットテーブルを指定することはできません。
回避策
create table term_hierarchy_backup (tid int(10)); <- check data type
insert into term_hierarchy_backup
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015;
DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (select tid from term_hierarchy_backup);
サブクエリの使用中にこの質問を削除するように見える他の人のために、MySQLの裏をかくためにこの例を残します(一部の人々はそれを行うことができないと思われる場合でも):
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM tableE
WHERE arg = 1 AND foo = 'bar');
エラーが発生します:
ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause
ただし、このクエリ:
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM (SELECT id
FROM tableE
WHERE arg = 1 AND foo = 'bar') x);
うまく動作します:
Query OK, 1 row affected (3.91 sec)
サブクエリを追加のサブクエリ(ここではx)でラップすると、MySQLが希望どおりに実行します。
エイリアスはDELETE
キーワードの後に含める必要があります。
DELETE th
FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN
(
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015
);
次のように、deleteステートメントでエイリアスを再度参照する必要があります。
DELETE th FROM term_hierarchy AS th
....
私はこれに少し異なる方法でアプローチしましたが、私にとってはうまくいきました。
条件行がなくなったconditions
テーブルを参照していたテーブルからsecure_links
を削除する必要がありました。基本的にはハウスキーピングスクリプト。これによりエラーが発生しました-削除するターゲットテーブルを指定できません。
そこで、ここからインスピレーションを探して、以下のクエリを思いつきました。これは、DELETEの参照として使用される一時テーブルsl1
を作成するためです。
DELETE FROM `secure_links` WHERE `secure_links`.`link_id` IN
(
SELECT
`sl1`.`link_id`
FROM
(
SELECT
`sl2`.`link_id`
FROM
`secure_links` AS `sl2`
LEFT JOIN `conditions` ON `conditions`.`job` = `sl2`.`job`
WHERE
`sl2`.`action` = 'something' AND
`conditions`.`ref` IS NULL
) AS `sl1`
)
私のために働く。
削除の「in」句ではないのですか...サブクエリから返される値が多数ある場合、非常に非効率的ですか? 「in(subquery)」ではなく、削除するIDのサブクエリから元のテーブルに対して内側(または右)だけで結合しない理由はわかりません。
DELETE T FROM Target AS T
RIGHT JOIN (full subquery already listed for the in() clause in answers above) ` AS TT ON (TT.ID = T.ID)
また、「MySQLは許可していません」で回答されているかもしれませんが、削除するものを完全に明確にする(DELETE T FROM Target AS T)ようにしてください。 MySQLの結合で削除 は、DELETE/JOINの問題を明確にします。
2つのクエリでこれを実行したい場合は、いつでもこれに似たことができます。
1)テーブルからIDを取得します:
SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ...
次に、マウス/キーボードまたはプログラミング言語を使用して、結果を以下のXXXにコピーします。
2) DELETE FROM your_table WHERE id IN ( XXX )
たぶん、1つのクエリでこれを行うことができますが、これは私が好むものです。
@ CodeReaper、@ BennyHill:期待どおりに動作します。
しかし、テーブルに数百万の行があるために時間の複雑さを疑問に思いますか?どうやら、正しくインデックス付けされたテーブルに5k個のレコードがあるため、5ms
を実行するのにかかったようです。
私のクエリ:
SET status = '1'
WHERE id IN (
SELECT id
FROM (
SELECT c2.id FROM clusters as c2
WHERE c2.assign_to_user_id IS NOT NULL
AND c2.id NOT IN (
SELECT c1.id FROM clusters AS c1
LEFT JOIN cluster_flags as cf on c1.last_flag_id = cf.id
LEFT JOIN flag_types as ft on ft.id = cf.flag_type_id
WHERE ft.slug = 'closed'
)
) x)```
Or is there something we can improve on my query above?