538 Stimmen

T-SQL: Auswählen von zu löschenden Zeilen über Joins

Szenario:

Nehmen wir an, ich habe zwei Tabellen, TabelleA und TabelleB. Der Primärschlüssel von TabelleB ist eine einzelne Spalte (BId) und ist eine Fremdschlüsselspalte in TabelleA.

In meiner Situation möchte ich alle Zeilen in TabelleA entfernen, die mit bestimmten Zeilen in TabelleB verknüpft sind: Kann ich das durch Joins erreichen? Alle Zeilen löschen, die aus den Joins gezogen werden?

DELETE FROM TableA 
FROM
   TableA a
   INNER JOIN TableB b
      ON b.BId = a.BId
      AND [my filter condition]

Oder bin ich gezwungen, dies zu tun:

DELETE FROM TableA
WHERE
   BId IN (SELECT BId FROM TableB WHERE [my filter condition])

Der Grund für meine Frage ist, dass mir die erste Option bei größeren Tabellen viel effizienter zu sein scheint.

Gracias.

3voto

DavidJ Punkte 3942

Die obige Syntax funktioniert in Interbase 2007 nicht. Stattdessen musste ich etwas verwenden wie:

DELETE FROM TableA a WHERE [filter condition on TableA] 
  AND (a.BId IN (SELECT a.BId FROM TableB b JOIN TableA a 
                 ON a.BId = b.BId 
                 WHERE [filter condition on TableB]))

(Hinweis: Interbase unterstützt das Schlüsselwort AS für Aliase nicht)

3voto

QMaster Punkte 3479

Ich benutze das

DELETE TableA 
FROM TableA a
INNER JOIN
TableB b on b.Bid = a.Bid
AND [condition]

und @TheTXI Weg ist gut, wie genug, aber ich Antworten und Kommentare lesen und ich fand ein Dinge muss beantwortet werden, ist mit Bedingung in WHERE-Klausel oder als Join-Bedingung. Also habe ich beschlossen, es zu testen und ein Snippet zu schreiben, aber ich habe keinen bedeutenden Unterschied zwischen ihnen gefunden. Sie können das Sql-Skript hier sehen und der wichtige Punkt ist, dass ich es vorgezogen habe, es als Kommnet zu schreiben, weil es keine exakte Antwort ist, aber es ist groß und kann nicht in die Kommentare geschrieben werden, bitte entschuldigen Sie mich.

Declare @TableA  Table
(
  aId INT,
  aName VARCHAR(50),
  bId INT
)
Declare @TableB  Table
(
  bId INT,
  bName VARCHAR(50)  
)

Declare @TableC  Table
(
  cId INT,
  cName VARCHAR(50),
  dId INT
)
Declare @TableD  Table
(
  dId INT,
  dName VARCHAR(50)  
)

DECLARE @StartTime DATETIME;
SELECT @startTime = GETDATE();

DECLARE @i INT;

SET @i = 1;

WHILE @i < 1000000
BEGIN
  INSERT INTO @TableB VALUES(@i, 'nameB:' + CONVERT(VARCHAR, @i))
  INSERT INTO @TableA VALUES(@i+5, 'nameA:' + CONVERT(VARCHAR, @i+5), @i)

  SET @i = @i + 1;
END

SELECT @startTime = GETDATE()

DELETE a
--SELECT *
FROM @TableA a
Inner Join @TableB b
ON  a.BId = b.BId
WHERE a.aName LIKE '%5'

SELECT Duration = DATEDIFF(ms,@StartTime,GETDATE())

SET @i = 1;
WHILE @i < 1000000
BEGIN
  INSERT INTO @TableD VALUES(@i, 'nameB:' + CONVERT(VARCHAR, @i))
  INSERT INTO @TableC VALUES(@i+5, 'nameA:' + CONVERT(VARCHAR, @i+5), @i)

  SET @i = @i + 1;
END

SELECT @startTime = GETDATE()

DELETE c
--SELECT *
FROM @TableC c
Inner Join @TableD d
ON  c.DId = d.DId
AND c.cName LIKE '%5'

SELECT Duration    = DATEDIFF(ms,@StartTime,GETDATE())

Wenn Sie gute Gründe für dieses Skript finden oder ein anderes nützliches Skript schreiben konnten, teilen Sie es bitte mit. Danke und hoffen, dass dies helfen.

2voto

beauXjames Punkte 7782

Nehmen wir an, Sie haben 2 Tabellen, eine mit einem Master-Set (z. B. Mitarbeiter) und eine mit einem Child-Set (z. B. Angehörige), und Sie möchten alle Datenzeilen in der Tabelle Angehörige loswerden, die nicht mit Zeilen in der Master-Tabelle übereinstimmen.

delete from Dependents where EmpID in (
select d.EmpID from Employees e 
    right join Dependents d on e.EmpID = d.EmpID
    where e.EmpID is null)

Der Punkt, der hier zu beachten ist, ist, dass Sie nur ein "Array" von EmpIDs aus der Verknüpfung zuerst sammeln, die Verwendung dieses Satzes von EmpIDs, um einen Löschvorgang auf der Tabelle Abhängige zu tun.

2voto

Bhoom Suktitipat Punkte 2071

In SQLite ist das Einzige, was funktioniert, etwas Ähnliches wie die Antwort von beauXjames.

Es scheint auf Folgendes hinauszulaufen DELETE FROM table1 WHERE table1.col1 IN (SOME TEMPORARY TABLE); und dass eine temporäre Tabelle durch SELECT und JOIN Ihrer beiden Tabellen erstellt werden kann, die Sie auf der Grundlage der Bedingung filtern können, dass Sie die Datensätze in Tabelle 1 löschen möchten.

1voto

Aditya Punkte 63

Sie können diese Abfrage ausführen:

    DELETE FROM TableA
    FROM
       TableA a, TableB b 
    WHERE
       a.Bid=b.Bid
    AND
       [my filter condition]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X