T-SQL: выбор строк для удаления через соединения

Сценарий:

Скажем, у меня есть две таблицы: TableA и TableB. Первичный ключ TableB представляет собой отдельный столбец (BId) и является столбцом внешнего ключа в TableA.

В моей ситуации я хочу удалить все строки в TableA, которые связаны с определенными строками в TableB: Могу ли я сделать это через соединения? Удалить все строки, вытянутые из соединений?

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

Причина, по которой я спрашиваю, заключается в том, что мне кажется, что первый вариант будет намного эффективнее при работе с большими таблицами.

Спасибо!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
507
0
409 527
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Ответ принят как подходящий
DELETE TableA
FROM   TableA a
       INNER JOIN TableB b
               ON b.Bid = a.Bid
                  AND [my filter condition] 

должно сработать

Я использовал And [мое условие фильтра] для соединения вместо предложения Where. Я предполагаю, что оба будут работать, но условие фильтрации соединения ограничит ваши результаты от соединения.

TheTXI 13.01.2009 19:51

Один вопрос. Почему нам нужно писать «УДАЛИТЬ TableA FROM» вместо «DELETE FROM»? Я вижу, это работает только в этом случае, но почему?

LaBracca 20.10.2010 17:53

Думаю, потому что нужно указать, из какой таблицы удалять записи. Я только что выполнил запрос с синтаксисом DELETE TableA, TableB ... и фактически удалил соответствующие записи из обоих. Хороший.

Andrew 25.12.2010 02:23

В PostgreSQL синтаксис с join не работает, но можно использовать ключевое слово using. DELETE from TableA a using TableB b where b.Bid = a.Bid and [my filter condition]

bartolo-otrit 13.06.2012 12:00

В MySQL вы получите сообщение об ошибке «Неизвестная таблица TableA в MULTI DELETE», потому что вы объявили псевдоним для TableA (a). Небольшая регулировка: DELETE a FROM TableA a INNER JOIN TableB b on b.Bid = a.Bid and [my filter condition]

masam 10.08.2012 10:34

У меня работает в SQL2008 +1

Andez 11.02.2013 21:09

У меня похожий вопрос. Я хочу удалить из обеих таблиц A и B. Как мне это сделать? Вопрос - stackoverflow.com/questions/21620018/… Спасибо.

Steam 07.02.2014 09:31

Этот ответ мне просто помог ... Спасибо и спасибо за базы знаний.

J.S. Orris 17.04.2014 23:29
DELETE a FROM TableA a ... ... - это правильный путь
Glauco Cucchiar 22.10.2019 13:31

Это не лучшее решение. Объединения следует использовать только тогда, когда пользователю необходимо получить данные из нескольких таблиц. Для DML, таких как обновления и удаления, вам нужно только уточнить совокупность. Таким образом, запрос на удаление должен относиться к 1 таблице, а затем вы присоединяетесь к подзапросу. мой ответ ниже.

1c1cle 03.12.2019 20:35

Да, ты можешь. Пример :

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

Я предпочитаю ссылаться на таблицу в первой строке по ее псевдониму. То есть «Удалить», а не «Удалить таблицу А». В случае, когда вы присоединяетесь к таблице с самим собой, он дает понять, с какой стороны вы хотите удалить.

Jeremy Stein 07.06.2012 18:18

Я бы использовал этот синтаксис

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

Я тоже предпочитаю этот синтаксис, который, кажется, имеет больше логического смысла в том, что происходит. Кроме того, я знаю, что вы можете использовать такой же синтаксис для ОБНОВЛЕНИЯ.

Adam Nofsinger 25.11.2010 00:58

Я тоже предпочитаю это, потому что размещение псевдонима таблицы после DELETE всегда казалось мне более интуитивным в отношении того, что удаляется.

Jagd 31.01.2012 23:22

На самом деле, это тоже предпочтительнее для меня. В частности, в тех случаях, когда мне действительно нужно присоединиться к одной и той же таблице (например, для удаления повторяющихся записей). В этом случае мне нужно использовать псевдоним для «стороны», с которой я удаляю, и этот синтаксис делает очень понятным, что я удаляю из псевдонима дубликатов.

Chris Simmons 21.02.2012 19:32

Это почти то же самое в MySQL, но вы должны использовать псевдоним таблицы сразу после слова "DELETE":

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

Пытался сделать это с помощью базы данных доступа и обнаружил, что мне нужно использовать а. * сразу после удаления.

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

Из отклоненного ожидающего редактирования: «Свойство UniqueRecords должно иметь значение« да », иначе оно не будет работать. (support.microsoft.com/kb/240098

StuperUser 03.01.2014 19:58

Приведенный выше синтаксис не работает в 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 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 для выполнения операции удаления в таблице зависимых.

В SQLite единственное, что работает, - это что-то вроде ответа beauXjames.

Кажется, все сводится к этому DELETE FROM table1 WHERE table1.col1 IN (SOME TEMPORARY TABLE); и что некоторая временная таблица может быть создана с помощью SELECT и JOIN ваших двух таблиц, которые вы можете фильтровать эту временную таблицу на основе условия, при котором вы хотите удалить записи в Table1.

Вы можете запустить этот запрос:

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

Я использую это

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

Если вы могли почерпнуть из этого сценария вескую причину или написать другой полезный, поделитесь. Спасибо и надеюсь, что это поможет.

Более простой способ:

DELETE TableA
FROM TableB
WHERE TableA.ID = TableB.ID
DELETE FROM table1
where id IN 
    (SELECT id FROM table2..INNER JOIN..INNER JOIN WHERE etc)

Сведите к минимуму использование запросов DML с помощью соединений. Вы должны уметь выполнять большинство всех запросов DML с подзапросами, как указано выше.

В общем, объединения следует использовать только тогда, когда вам нужно ВЫБРАТЬ или ГРУППИРОВАТЬ по столбцам в 2 или более таблицах. Если вы Только касаетесь нескольких таблиц для определения совокупности, используйте подзапросы. Для запросов DELETE используйте коррелированный подзапрос.

Другие вопросы по теме