Löschen Sie alle Zeilen in einer Tabelle basierend auf einer anderen Tabelle

80

Ich kann mich anscheinend nie an diese Frage erinnern!

Ich möchte alle Zeilen in Tabelle1 löschen, deren IDs mit denen in Tabelle2 übereinstimmen.

Damit:

DELETE table1 t1
 WHERE t1.ID = t2.ID

Ich weiß, dass ich eine WHERE ID IN (SELECT ID FROM table2) ausführen kann, aber ich möchte diese Abfrage nach Möglichkeit mit einem JOIN durchführen.

mrblah
quelle
Warum möchten Sie einen Join machen?
Tster
Was planen Sie mit dieser Frage zu tun: stackoverflow.com/questions/1590709/…
OMG Ponies
Weil Joins oft schneller sind.
HLGEM
@tster Vielleicht ist es eine temporäre Tabelle von IDs, die gelöscht werden müssen
Stephen Mesa
1
@HLGEM Wollen Sie damit sagen, dass das Abfrageoptimierungsprogramm nicht intelligent genug ist, um ein einfaches "Löschen von X, bei dem XY IN (Foo aus Balken auswählen)" so schnell wie ein Join durchzuführen? Ich würde dem Optimierer über das Bauchgefühl vertrauen.
Tster

Antworten:

88
DELETE Table1
FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.ID
Stephen Mesa
quelle
87
DELETE t1 
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID;

Ich verwende immer den Alias ​​in der delete-Anweisung, da er das Versehen verhindert

DELETE Table1 

Wird verursacht, wenn die gesamte Abfrage vor dem Ausführen nicht hervorgehoben werden kann.

HLGEM
quelle
5
Upvoting hauptsächlich für den Kommentar "Immer den Alias ​​verwenden". Großartige Idee.
Rosscova
35

In ANSI SQL gibt es keine Lösung für die Verwendung von Joins beim Löschen, AFAIK.

DELETE FROM Table1
WHERE Table1.id IN (SELECT Table2.id FROM Table2)

Später bearbeiten

Andere Lösung (manchmal schneller):

DELETE FROM Table1
WHERE EXISTS( SELECT 1 FROM Table2 Where Table1.id = Table2.id)
Cătălin Pitiș
quelle
Seine Frage besagt am Ende, dass er einen Join anstelle der IN-Klausel verwenden möchte.
Stephen Mesa
21

PostgreSQL-Implementierung wäre:

DELETE FROM t1
USING t2
WHERE t1.id = t2.id;
Vesanto
quelle
4

Versuche dies:

DELETE Table1
FROM Table1 t1, Table2 t2
WHERE t1.ID = t2.ID;

oder

DELETE Table1
FROM Table1 t1 INNER JOIN Table2 t2 ON t1.ID = t2.ID;
Yannick Motton
quelle
3

Ich denke, dass Sie ein bisschen mehr Leistung bekommen könnten, wenn Sie dies versuchen würden

DELETE FROM Table1
WHERE EXISTS (
  SELECT 1
  FROM Table2
  WHERE Table1.ID = Table2.ID
)
Bogertron
quelle
3

Dadurch werden alle Zeilen gelöscht Table1, die den Kriterien entsprechen:

DELETE Table1 
FROM Table2 
WHERE Table1.JoinColumn = Table2.JoinColumn And Table1.SomeStuff = 'SomeStuff'
Mehr
quelle
2

Diesen Link gefunden nützlich

Von dort kopiert

Oft möchte man einige Datensätze aus einer Tabelle löschen, basierend auf Kriterien in einer anderen Tabelle. Wie können Sie aus einer dieser Tabellen löschen, ohne die Datensätze in beiden Tabellen zu entfernen?

DELETE DeletingFromTable
     FROM DeletingFromTable INNER JOIN CriteriaTable
     ON DeletingFromTable.field_id = CriteriaTable.id
     WHERE CriteriaTable.criteria = "value";

Der Schlüssel ist, dass Sie den Namen der Tabelle, aus der gelöscht werden soll, als SELECT angeben . Also nehmen JOIN und WHERE die Auswahl und Begrenzung vor, während DELETE das Löschen vornimmt. Sie sind jedoch nicht auf nur einen Tisch beschränkt. Wenn Sie eine Viele-zu-Viele-Beziehung haben (z. B. Zeitschriften und Abonnenten, verbunden mit einem Abonnement) und einen Abonnenten entfernen, müssen Sie auch alle potenziellen Datensätze aus dem Join-Modell entfernen.

 DELETE subscribers, subscriptions
     FROM subscribers INNER JOIN subscriptions 
       ON subscribers.id = subscriptions.subscriber_id
     INNER JOIN magazines 
       ON subscriptions.magazine_id = magazines.id
     WHERE subscribers.name='Wes';

Das Löschen von Datensätzen mit einem Join kann auch mit einem LEFT JOIN und einem WHERE erfolgen, um festzustellen, ob die verknüpfte Tabelle NULL war, sodass Sie Datensätze in einer Tabelle entfernen können, für die keine Übereinstimmung vorliegt (z. B. zur Vorbereitung des Hinzufügens einer Beziehung). ) Beispielbeitrag kommt noch.

Ankur Gupta
quelle
2

Da das OP nicht nach einer bestimmten Datenbank fragt, verwenden Sie besser eine standardkonforme Anweisung. Nur MERGEin SQL-Standard zum Löschen (oder Aktualisieren) von Zeilen, während etwas in der Zieltabelle verbunden wird.

merge table1 t1
    using (
        select t2.ID
            from table2 t2
    ) as d
    on t1.ID = d.ID
    when matched then delete;

MERGEhat eine strengere Semantik, die vor einigen Fehlerfällen schützt, die unbemerkt bleiben können DELETE ... FROM. Es erzwingt die Eindeutigkeit der Übereinstimmung: Wenn viele Zeilen in der Quelle (die darin enthaltene Anweisung using) mit derselben Zeile im Ziel übereinstimmen, muss die Zusammenführung abgebrochen und ein Fehler von der SQL-Engine ausgelöst werden.

Frédéric
quelle
Dies ist sauberer als Delete-Join-Konstrukt
Asakura89
0

Referenzieren von MSDN T-SQL DELETE (Beispiel D):

DELETE FROM Table1
FROM Tabel1 t1
   INNER JOIN Table2 t2 on t1.ID = t2.ID
Austin Salonen
quelle
0

Löschen von Tabellendatensätzen basierend auf einer anderen Tabelle

     Delete From Table1 a,Table2 b where a.id=b.id

    Or

      DELETE FROM Table1
    WHERE Table1.id IN (SELECT Table2.id FROM Table2)

  Or

        DELETE Table1
     FROM Table1 t1 INNER JOIN Table2 t2 ON t1.ID = t2.ID;
Kavitha Reddy
quelle
0

Das ist alt, ich weiß, aber nur ein Hinweis auf jemanden, der diesen Arsch benutzt, eine Referenz. Ich habe es gerade versucht und wenn Sie Oracle verwenden, funktioniert JOIN in DELETE-Anweisungen nicht. Sie erhalten folgende Meldung:

ORA-00933: SQL-Befehl nicht ordnungsgemäß beendet.

KS1
quelle
In dieser Antwort auf eine andere Frage finden Sie ein Beispiel für das Schreiben eines Löschvorgangs mit Join unter Oracle.
Frédéric
0

Während das OP keine 'in'-Anweisung verwenden möchte, war dies als Antwort auf Ankur Gupta der einfachste Weg, die Datensätze in einer Tabelle zu löschen, die in einer anderen Tabelle nicht vorhanden waren, in einer Eins-zu-Viele-Beziehung ::

DELETE
FROM Table1 as t1
WHERE ID_Number NOT IN
(SELECT ID_Number FROM Table2 as t2)

Hat für mich in Access 2016 wie ein Zauber funktioniert.

rauben
quelle
0

Ich mache oft Dinge wie das folgende erfundene Beispiel. (Dieses Beispiel stammt von Informix SE unter Linux.)

In diesem Beispiel werden alle Datensätze für Immobilienfreistellungs- / -reduzierungstransaktionen gelöscht, da die Minderungsanwendung einen Fehler aufweist. Diese basieren auf Informationen in der Tabelle "real_estate".

In diesem Fall last_update != nullbedeutet dies, dass das Konto nicht geschlossen ist und res_exempt != 'p'dass die Konten kein persönliches Eigentum sind (gewerbliche Geräte / Einrichtungsgegenstände).

delete from trans 
where   yr = '16'
and     tran_date = '01/22/2016'
and     acct_type = 'r'
and     tran_type = 'a'
and     bill_no in
(select acct_no from real_estate where last_update is not null
 and res_exempt != 'p');

Ich mag diese Methode, weil die Filterkriterien - zumindest für mich - beim Erstellen der Abfrage leichter zu lesen sind und in vielen Monaten zu verstehen sind, wenn ich sie betrachte und mich frage, was ich gedacht habe.

Octopusgrabbus
quelle
0
delete
    table1
from 
    t2
where
    table1.ID=t2.ID

Funktioniert auf mssql

Ken Kin
quelle