it-swarm.com.de

T-SQL: Auswählen von Zeilen zum Löschen über Joins

Szenario:

Angenommen, ich habe zwei Tabellen, TableA und TableB. Der Primärschlüssel von TableB ist eine einzelne Spalte (BId) und eine Fremdschlüsselspalte in TableA.

In meiner Situation möchte ich alle Zeilen in TableA entfernen, die mit bestimmten Zeilen in TableB verknüpft sind: Kann ich das über Joins tun? Alle Zeilen löschen, die aus den Joins gezogen wurden?

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

Oder bin ich dazu gezwungen:

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

Der Grund, den ich frage, scheint mir, dass die erste Option beim Umgang mit größeren Tabellen viel effizienter wäre.

Vielen Dank!

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

sollte arbeiten

704
TheTXI

Ich würde diese Syntax verwenden

Delete a 
from TableA a
Inner Join TableB b
on  a.BId = b.BId
WHERE [filter condition]
257
cmsjr

Ja, du kannst. Beispiel

DELETE TableA 
FROM TableA AS a
INNER JOIN TableB AS b
ON a.BId = b.BId
WHERE [filter condition]
29
Diadistis

Ich habe versucht, dies mit einer Zugriffsdatenbank zu tun, und habe festgestellt, dass ich a. * direkt nach dem Löschen verwenden muss.

DELETE a.*
FROM TableA AS a
INNER JOIN TableB AS b
ON a.BId = b.BId
WHERE [filter condition]
10
Tony Emrud

Es ist fast dasselbe in MySQL, aber Sie müssen das Tabellenalias direkt nach dem Wort "DELETE" verwenden:

DELETE a
FROM TableA AS a
INNER JOIN TableB AS b
ON a.BId = b.BId
WHERE [filter condition]
8
Michael Butler

Ich benutze das

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

und @TheTXI Weg ist so gut wie genug, aber ich las Antworten und Kommentare und fand, dass eine Sache, die beantwortet werden muss, die Verwendung der Bedingung in der WHERE-Klausel oder als Join-Bedingung ist. Also habe ich beschlossen, es zu testen und ein Snippet zu schreiben, aber keinen signifikanten Unterschied gefunden. Sie können das SQL-Skript hier sehen. Ein wichtiger Punkt ist, dass ich es lieber als Commnet geschrieben habe, da dies keine exakte Antwort ist, es aber groß ist und keine Kommentare enthalten kann. 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 haben oder ein anderes nützliches Skript schreiben könnten, teilen Sie dies bitte mit. Danke und hoffe diese Hilfe.

2
QMaster

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

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 AS-Schlüsselwort für Aliase nicht.)

2
DavidJ

sie können diese Abfrage ausführen: -

Delete from TableA 
from 
TableA a, TableB b 
where a.Bid=b.Bid
AND [my filter condition]
1
Aditya

Angenommen, Sie haben zwei Tabellen, eine mit einem Master-Satz (z. B. Employees) und eine mit einem untergeordneten Satz (z. B. Dependents), und Sie möchten alle Datenzeilen in der Dependents-Tabelle entfernen, die nicht verschlüsselt werden können mit beliebigen Zeilen in der Master-Tabelle.

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)

Hier ist zu beachten, dass Sie nur ein 'Array' von EmpIDs aus dem Join sammeln und diesen Satz von EmpIDs verwenden, um einen Löschvorgang für die Tabelle Dependents durchzuführen.

1
beauXjames

In SQLite ist das einzige, was funktioniert, die Antwort von beauXjames.

Es scheint, als käme es auf dieses DELETE FROM table1 WHERE table1.col1 IN (SOME TEMPORARY TABLE); an, und dass eine temporäre Tabelle durch SELECT und JOIN in Ihren beiden Tabellen erstellt werden kann. Sie können diese temporäre Tabelle basierend auf der Bedingung filtern, dass Sie die Datensätze in Tabelle1 löschen möchten.

1

Der einfachere Weg ist:

DELETE TableA
FROM TableB
WHERE TableA.ID = TableB.ID
0
Carlos Barini