Wie lösche ich aus select in MySQL?

86

Dieser Code funktioniert nicht für MySQL 5.0. So schreiben Sie ihn neu, damit er funktioniert

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

Ich möchte Spalten löschen, die keine eindeutige ID haben. Ich werde hinzufügen, dass es die meiste Zeit nur eine ID ist (ich habe die In-Syntax ausprobiert und es funktioniert auch nicht).

IAdapter
quelle

Antworten:

209

SELECT(sub) Abfragen geben Ergebnismengen . Sie müssen also INnicht =in Ihrer WHEREKlausel verwenden.

Wie in dieser Antwort gezeigt , können Sie außerdem nicht dieselbe Tabelle aus einer Unterabfrage innerhalb derselben Abfrage ändern. Sie können SELECTdann jedoch entweder DELETEin separaten Abfragen oder eine andere Unterabfrage verschachteln und das Ergebnis der inneren Unterabfrage aliasisieren (sieht jedoch ziemlich hackig aus):

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

Oder verwenden Sie Joins, wie von Mchl vorgeschlagen .

BoltClock
quelle
1
Ich hatte eine Tabelle mit 150 doppelten Schlüsseln. Ich habe die obige Abfrage ausgeführt und es stand "144 Zeilen betroffen", aber dort waren noch doppelte Schlüssel. Also habe ich die Abfrage erneut ausgeführt und es steht wieder 5 betroffene Zeilen: 1 betroffene Zeile. Dann waren alle doppelten Schlüssel weg. Warum ist das?
Alex
Dies geschieht, weil Sie nur 1 Eintrag aus jedem Satz von Duplikaten löschen:SELECT id FROM posts GROUP BY id HAVING ( COUNT(id) > 1 )
Havvg
# 1248 - Jede abgeleitete Tabelle muss einen eigenen Alias ​​haben
thang
@thang: Deshalb habe ich gesagt, alias die innere Unterabfrage.
BoltClock
1
Erklären Sie bitte, was das "As p" bewirkt.
Cricketspieler
22
DELETE 
  p1
  FROM posts AS p1 
CROSS JOIN (
  SELECT ID FROM posts GROUP BY id HAVING COUNT(id) > 1
) AS p2
USING (id)
Mchl
quelle
Dies scheint zu funktionieren, aber ich bin durch die Syntax verwirrt und kann an keiner anderen Stelle Ressourcen finden, um dies zu erklären. CROSS JOINführt anscheinend eine kartesische Verknüpfung durch, scheint also unnötige Arbeit zu leisten oder suboptimal zu arbeiten? Könnte jemand erklären?
Wintron
Ein kartesisches Produkt wird nur dann ausgeführt, wenn keine USINGKlausel vorhanden ist. Da USINGdas Produkt auf Paare mit dem gleichen Wert in der idSpalte beschränkt ist, ist es in der Tat sehr begrenzt.
Mchl
Könnten Sie dasselbe mit inner join tun? IEDELETE p1 FROM posts AS p1 INNER JOIN ( SELECT ID FROM posts GROUP BY id HAVING COUNT(id) > 1 ) AS p2 ON p2.ID=p1.ID
Kodos Johnson
1
@ Andrew: Ja. Funktionell sind diese Verknüpfungen genau gleich.
Mchl
5

Sie können Inner Join verwenden:

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  
Charif DZ
quelle
0

Wenn Sie alle Duplikate löschen möchten, jedoch eines aus jedem Satz von Duplikaten, ist dies 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;
havvg
quelle