T-SQL : 조인을 통해 삭제할 행 선택


494

대본:

TableA와 TableB라는 두 개의 테이블이 있다고 가정 해 봅시다. TableB의 기본 키는 단일 열 (BId)이며 TableA의 외래 키 열입니다.

내 상황에서 TableB의 특정 행과 연결된 TableA의 모든 행을 제거하고 싶습니다. 조인을 통해 수행 할 수 있습니까? 조인에서 가져온 모든 행을 삭제 하시겠습니까?

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

아니면이 작업을 수행해야합니까?

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

내가 묻는 이유는 큰 테이블을 다룰 때 첫 번째 옵션이 훨씬 효율적이라고 생각하기 때문입니다.

감사!

답변:


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

작동해야합니다


1
Where 절 대신 조인에 And [my filter condition]을 사용했습니다. 두 가지 모두 효과가 있다고 생각하지만 조인의 필터 조건으로 인해 조인의 결과가 제한됩니다.
TheTXI

10
하나의 질문. 왜 'DELETE FROM'대신 'DELETE TableA FROM'을 작성해야합니까? 이 경우에만 작동하지만 왜 그럴까요?
LaBracca

66
레코드를 삭제할 테이블을 표시해야하기 때문에 생각합니다. 방금 구문으로 쿼리를 실행했으며 DELETE TableA, TableB ...실제로 두 레코드에서 관련 레코드를 삭제했습니다. 좋은.
앤드류

1
join이 포함 된 PostgreSQL 구문에서는 작동하지 않지만 "using"키워드를 사용할 수 있습니다. DELETE from TableA a using TableB b where b.Bid = a.Bid and [my filter condition]
bartolo-otrit

8
MySQL에서는 "MULTI DELETE의 '알 수없는 테이블'TableA '"오류가 발생하며 이는 TableA (a)에 대한 별칭을 선언했기 때문입니다. 작은 조정 :DELETE a FROM TableA a INNER JOIN TableB b on b.Bid = a.Bid and [my filter condition]
masam

260

나는이 문법을 사용할 것이다

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

7
나는이 구문도 선호하며, 논리적으로 진행되는 것을 조금 더 이해하는 것처럼 보입니다. 또한 UPDATE에 동일한 유형의 구문을 사용할 수 있다는 것을 알고 있습니다.
Adam Nofsinger

DELETE 뒤에 테이블 별칭을 배치하면 삭제되는 대상에 대해 항상 더 직관적 인 것처럼 보였으므로 선호합니다.
Jagd

14
실제로 이것은 나에게도 선호됩니다. 특히 동일한 테이블에서 실제로 조인해야하는 경우 (예 : 중복 레코드 삭제) 이 경우 삭제중인 "사이드"에 별칭을 사용해야하며이 구문을 사용하면 중복 별칭에서 삭제하는 것이 매우 명확 해집니다.
Chris Simmons

29

그래 넌 할수있어. 예 :

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

8
첫 번째 줄의 별칭을 테이블을 참조하는 것이 좋습니다. "Delete TableA"가 아니라 "Delete a"입니다. 테이블 자체를 조인하는 경우 삭제할 쪽을 명확하게합니다.
Jeremy Stein

10

액세스 데이터베이스 로이 작업을 시도 했지만 삭제 직후 a. * 를 사용해야 한다는 것을 알았습니다 .

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

거부중인 편집에서 ". UniqueRecords 속성은 yes로 설정해야합니다 그렇지 않으면하지 않습니다 작업 (이 support.microsoft.com/kb/240098 )"
StuperUser

8

MySQL 에서는 거의 동일 하지만 "DELETE"라는 단어 바로 뒤에 테이블 별칭 을 사용해야합니다 .

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

2

위의 구문은 Interbase 2007에서 작동하지 않습니다. 대신 다음과 같은 것을 사용해야했습니다.

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]))

(참고 Interbase는 별칭에 AS 키워드를 지원하지 않습니다)


2

나는 이것을 사용하고있다

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

@TheTXI 방법은 충분하지만 답변과 의견을 읽었으며 WHERE 절의 조건을 사용하거나 조인 조건으로 응답 해야하는 것을 발견했습니다. 그래서 나는 그것을 테스트하고 스 니펫을 작성하기로 결정했지만 그들 사이의 의미있는 차이점을 찾지 못했습니다. 여기에서 SQL 스크립트를 볼 수 있으며 중요한 점은 정확한 답변이 아니기 때문에 commnet으로 작성하는 것을 선호한다는 것입니다.

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())

이 스크립트에서 충분한 이유를 얻거나 다른 유용한 정보를 작성할 수 있다면 공유하십시오. 이 도움을 주셔서 감사합니다.


1

마스터 세트 (예 : 직원)와 하위 세트 (예 : 부양 가족)가있는 테이블 2 개가 있고 키를 사용할 수없는 부양 가족 테이블의 모든 데이터 행을 제거하려고한다고 가정합니다. 마스터 테이블에 행이 있습니다.

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)

여기서 주목해야 할 점은 조인에서 EmpID의 '배열'을 먼저 수집하고, 해당 EmpID 세트를 사용하여 종속 테이블에서 삭제 조작을 수행한다는 것입니다.


1

SQLite에서 작동하는 유일한 것은 beauXjames의 대답과 비슷합니다.

아래로 내려 가서 DELETE FROM table1 WHERE table1.col1 IN (SOME TEMPORARY TABLE); 일부 임시 테이블을 SELECT하고 JOIN하여 두 테이블을 만들 수 있습니다.이 테이블은 Table1의 레코드를 삭제하려는 조건에 따라이 임시 테이블을 필터링 할 수 있습니다.


1

이 쿼리를 실행할 수 있습니다 :-

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


1
DELETE FROM table1
where id IN 
    (SELECT id FROM table2..INNER JOIN..INNER JOIN WHERE etc)

조인으로 DML 쿼리 사용을 최소화하십시오. 위와 같은 하위 쿼리를 사용하여 대부분의 모든 DML 쿼리를 수행 할 수 있어야합니다.

일반적으로 조인은 두 개 이상의 테이블에서 열을 기준으로 SELECT 또는 GROUP을 수행해야하는 경우에만 사용해야합니다. 당신이 경우 인구를 정의하는 감동 여러 테이블을, 하위 쿼리를 사용합니다. DELETE 쿼리의 경우 상관 하위 쿼리를 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.