Эффективное удаление записей с T-SQL без использования предложения IN - PullRequest
0 голосов
/ 09 октября 2018

Существует ли эффективный способ удаления записей из SQL Server без использования ключевого слова IN в следующем сценарии:

-- If Documents were deleted, remove them from your ocean
DELETE FROM IndexHistory 
WHERE DocId IN (SELECT IH.Docid 
                FROM IndexHistory IH 
                LEFT JOIN IndexedLineItems I ON IH.Docid = I.DocId
                WHERE I.Docid IS NULL)

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

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

Так, например, я думаю, что-то вродеэто может быть возможно, но у меня нет правильного синтаксиса:

DELETE FROM IndexHistory IH 
LEFT JOIN IndexedLineItems I ON IH.Docid = I.DocId
WHERE I.Docid IS NULL

Я ценю, что ответ может быть «нет, это невозможно».

Если это невозможноВозможно, это может быть возможным предложением улучшить язык для Microsoft.Перед тем, как сделать это, я подумал, что я опубликую здесь, чтобы увидеть, что я что-то упустил.

Ответы [ 4 ]

0 голосов
/ 09 октября 2018

Это прекрасно работает ...

DELETE IH
    FROM IndexHistory IH
    Left JOIN IndexedLineItems LI
      ON IH.Docid = LI.DocId
    WHERE LI.DocId is Null
0 голосов
/ 09 октября 2018

Использование not exists:

Delete ih from IndexHistory ih
    where not exists (select 1 from IndexedLineItems ili where ih.Docid = ili.DocId)
0 голосов
/ 09 октября 2018

С другой стороны, используйте вместо этого внутреннее объединение, поэтому вы удаляете только совпадения:

DELETE FROM IndexHistory IH 
JOIN IndexedLineItems I ON IH.Docid = I.DocId
WHERE I.Docid IS NOT NULL
0 голосов
/ 09 октября 2018

Я предпочитаю CTE для удобства чтения, его также можно изменить, чтобы использовать SELECT, чтобы увидеть, что я собираюсь удалить.Это NOT EXISTS также может быть более эффективным:

WITH DeleteData AS
(
  SELECT IH.Docid 
  FROM IndexHistory IH 
  WHERE NOT EXISTS( SELECT 1 FROM IndexedLineItems I
                    WHERE I.DocId = IH.DocId)
)
DELETE FROM DeleteData

Вам не нужно дополнительное JOIN из этого CTE к таблице, потому что выбрана только одна таблица.

...