2010-12-30 6 views
61

Dieser Code für MySQL 5.0 nicht funktioniert, wie es neu zu schreiben, um esWie aus Select in MySQL löschen?

DELETE FROM posts where id=(SELECT id FROM posts GROUP BY id HAVING (COUNT(id) > 1)) 

I Spalten löschen möchten arbeiten zu machen, die eindeutige ID nicht haben. Ich werde hinzufügen, dass die meiste Zeit seine einzige ID (Ich versuchte die Syntax und es funktioniert nicht so gut).

Antwort

144

SELECT (Sub-) Abfragen liefern Ergebnis Sätze. Sie müssen also IN, nicht = in Ihrer WHERE Klausel verwenden.

Darüber hinaus, wie in this answer gezeigt, können Sie nicht die gleiche Tabelle aus einer Unterabfrage innerhalb der gleichen Abfrage ändern. Sie können jedoch entweder SELECT dann DELETE in separaten Abfragen oder nisten eine andere Unterabfrage und alias der innere Unterabfrage Ergebnis (sieht eher Hacky, obwohl):

DELETE FROM posts WHERE id IN (
    SELECT * FROM (
     SELECT id FROM posts GROUP BY id HAVING (COUNT(id) > 1) 
    ) AS p 
) 

oder benutzen verbindet as suggested by Mchl.

+1

Ich hatte eine Tabelle mit 150 doppelten Schlüsseln. Ich führte die obige Abfrage aus und es sagte "144 Zeilen betroffen", aber dort waren noch doppelte Schlüssel. Also habe ich die Abfrage erneut ausgeführt und es heißt, dass 5 Zeilen betroffen sind, wiederum: 1 Zeile betroffen. Dann sind alle doppelten Schlüssel verschwunden. Warum ist das? – Alex

+0

Dies passiert, weil Sie nur einen Eintrag aus jeder Menge von Duplikaten löschen: 'SELECT ID FROM Beiträge GROUP BY ID HAVING (COUNT (id)> 1)' – havvg

+0

# 1248 - Jede abgeleitete Tabelle muss ihren eigenen Alias ​​ – thang

19
DELETE 
    p1 
    FROM posts AS p1 
CROSS JOIN (
    SELECT ID FROM posts GROUP BY id HAVING COUNT(id) > 1 
) AS p2 
USING (id) 
+0

Dies scheint zu funktionieren, aber ich bin durch die Syntax verwirrt und kann keine Ressourcen finden anderswo, um es zu erklären. "CROSS JOIN" führt scheinbar eine kartesische Verbindung durch, scheint also unnötige Arbeit zu leisten oder suboptimal zu arbeiten? Könnte jemand erklären? – wintron

+0

Es wird ein kartesisches Produkt nur dann ausgeführt, wenn es keine 'USING'-Klausel gibt. Mit 'USING' ist das Produkt auf Paare beschränkt, die denselben Wert in der 'id'-Spalte haben, also ist es in der Tat sehr begrenzt. – Mchl

+1

Fantastische Lösung. –

-1

Wenn Sie alle Duplikate löschen möchten, aber eine von jedem Satz von Duplikaten, das ist eine Lösung:

DELETE posts 
FROM posts 
LEFT JOIN (
    SELECT id 
    FROM posts 
    GROUP BY id 
    HAVING COUNT(id) = 1 

    UNION 

    SELECT id 
    FROM posts 
    GROUP BY id 
    HAVING COUNT(id) != 1 
) AS duplicate USING (id) 
WHERE duplicate.id IS NULL; 
2

Sie können innere verwenden beitreten:

DELETE 
    ps 
FROM 
    posts ps INNER JOIN 
     (SELECT 
      distinct id 
     FROM 
      posts 
     GROUP BY id 
     HAVING COUNT(id) > 1) dubids on dubids.id = ps.id