Ich versuche eine Abfrage wie diese zu machen:
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
);
Wie Sie wahrscheinlich sagen können, möchte ich die übergeordnete Relation zu 1015 löschen, wenn dasselbe Tid andere Eltern hat. Das ergibt jedoch einen Syntaxfehler:
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
Ich habe die Dokumentation überprüft und die Unterabfrage selbst ausgeführt, und es scheint alles auszuprobieren. Kann jemand herausfinden, was hier los ist?
Update : Wie unten angegeben, erlaubt MySQL nicht, dass die Tabelle, aus der Sie löschen, in einer Unterabfrage für die Bedingung verwendet wird.
Sie können keine Zieltabelle zum Löschen angeben.
Eine Problemumgehung
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);
Für andere, die diese Frage bei der Verwendung einer Unterabfrage löschen möchten, gebe ich Ihnen dieses Beispiel, um MySQL zu überlisten (selbst wenn einige Leute meinen, dass dies nicht möglich ist):
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM tableE
WHERE arg = 1 AND foo = 'bar');
gibt dir einen Fehler:
ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause
Jedoch diese Abfrage:
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM (SELECT id
FROM tableE
WHERE arg = 1 AND foo = 'bar') x);
wird gut funktionieren:
Query OK, 1 row affected (3.91 sec)
Packen Sie Ihre Unterabfrage in eine zusätzliche Unterabfrage (hier mit dem Namen x) ein, und MySQL erledigt das, was Sie möchten.
Der Alias sollte nach dem Schlüsselwort DELETE
eingefügt werden:
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
);
Sie müssen in der delete -Anweisung erneut auf den Alias verweisen, z.
DELETE th FROM term_hierarchy AS th
....
Ich ging das etwas anders an und es funktionierte für mich.
Ich musste secure_links
aus meiner Tabelle entfernen, die auf die conditions
-Tabelle verwies, in der keine Bedingungszeilen mehr vorhanden waren. Grundsätzlich ein Housekeeping-Skript. Dies gab mir den Fehler - Sie können keine Zieltabelle zum Löschen angeben.
Auf der Suche nach Inspiration hierher kam ich mit der untenstehenden Abfrage und sie funktioniert gut .. __ Dies ist so, weil sie eine temporäre Tabelle sl1
erstellt, die als Referenz für DELETE verwendet wird.
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`
)
Funktioniert bei mir.
Ist die "in" -Klausel nicht in delete, wo extrem ineffizient, wenn eine große Anzahl von Werten von der Unterabfrage zurückgegeben wird? Nicht sicher, warum Sie sich nicht einfach nach innen (oder nach rechts) gegen die ursprüngliche Tabelle aus der Unterabfrage der ID löschen lassen möchten, statt uns das "in (Unterabfrage)".
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)
Und vielleicht wird darauf in "MySQL nicht erlaubt" geantwortet, aber es funktioniert gut für mich VORGESTELLT Ich vergewissere mich, dass Sie vollständig klarstellen, was gelöscht werden soll (DELETE T FROM Target AS T). Mit Join in MySQL löschen klärt das DELETE/JOIN-Problem.
Wenn Sie dies mit zwei Abfragen durchführen möchten, können Sie immer etwas Ähnliches tun:
1) nimm IDs aus der Tabelle mit:
SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ...
Kopieren Sie dann das Ergebnis mit der Maus/Tastatur oder der Programmiersprache nach XXX:
2) DELETE FROM your_table WHERE id IN ( XXX )
Vielleicht könnten Sie dies in einer Abfrage tun, aber das ist mir lieber.
@CodeReaper, @BennyHill: Es funktioniert wie erwartet.
Ich frage mich jedoch, wie komplex es ist, Millionen Zeilen in der Tabelle zu haben. Anscheinend brauchte es etwa 5ms
, um 5k Datensätze in einer korrekt indizierten Tabelle zu haben.
Meine Anfrage:
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?