2017-01-05 4 views
1

Ich suche, über einen Subselect zu löschen. Die Antworten für diese Frage lösen mein Problem nicht: MySQL Error 1093 - Can't specify target table for update in FROM clause.Löschen mit Subselect

fand ich einen hackish Weg, dies zu tun und wollte Feedback bekommen, wenn dies die optimale Lösung ein DELETE with SUBSELECT zu tun -

DELETE FROM main_history WHERE id NOT IN (
    SELECT * from (
    SELECT max(id) FROM main_history h GROUP BY instance_id, xpath 
    ) x 
) 

Grundsätzlich ich nur hinzufügen, in einem zweiten (sinnlos) subselect um den mySQL-Fehler zu erhalten, die ich erhalten, wenn ich mit dem subselect nur ein normaler lösche:

DELETE FROM main_history WHERE id NOT IN (
    SELECT max(id) FROM main_history h GROUP BY instance_id, xpath 
); 

Sie nicht Zieltabelle ‚main_history‘ for update in FROM-Klausel angeben

Ist dies eine gute Lösung für das oben genannte Problem?

Update: Die Subselect-Abfrage führt viel besser als die Join-Abfrage. Hier waren meine Ergebnisse:

# 12m Subselect 
DELETE FROM main_history WHERE id NOT IN (
SELECT * from (
    SELECT max(id) FROM main_history h GROUP BY instance_id, xpath 
) x 
) 

# 18m Join 
Delete m1 from main_history m1 left join 
(
    SELECT max(id) id FROM main_history h GROUP BY instance_id, xpath 
) m2 on m1.id = m2.id 
Where m2.id is null; 
+1

Was war der Fehler? – Anand

+0

@Anand siehe aktualisierte Frage pls. – David542

+0

Sie können der Tabelle auch ein neues boolesches Feld hinzufügen: "next_in_group" (mit Index). Es wäre wahr, wenn Sie einen neuen Eintrag hinzufügen und diesen Wert für alle anderen Einträge, in denen instance_id und xpath identisch sind (diese könnten einen zusammengesetzten Index haben), auf false setzen. Dann können Sie mit einer logarithmischen Abfrage löschen. –

Antwort

2

richtige Weg ist, mit löschen beitreten :

Delete m1 from main_history m1 left join 
(
    SELECT max(id) id FROM main_history h GROUP BY instance_id, xpath 
) m2 on m1.id = m2.id 
Where m2.id is null; 
+0

wollen die beiden verschiedenen Ansätze mit einigen gefälschten Daten Benchmarking, um zu sehen, welche besser funktioniert? – David542

+0

Was wäre der Unterschied zwischen dem Subselect-Ansatz und dem Join-Ansatz? – David542

+0

Ich wette, das ist die effizienteste Methode. – Anand

0

Sie können eine abgeleitete Tabelle wie folgt verwenden, dann MySQL kann nicht die Tabellenname aus der SELECT sehen:

DELETE FROM main_history WHERE id NOT IN (
    SELECT * FROM (
     SELECT * from (SELECT max(id) FROM main_history h 
     GROUP BY instance_id, xpath) AS x 
    ) AS delrows 
); 
+0

Was wäre der Unterschied zwischen dem Löschen und dem Löschen über einen Join, wie in der anderen Antwort? – David542