如何在WHERE中使用SELECT进行DELETE FROM工作?

Ala*_*an2 0 sql sql-server

我正在看一个应用程序,我发现这个SQL:

DELETE FROM Phrase 
WHERE Modified < (SELECT Modified FROM PhraseSource WHERE Id = Phrase.PhraseId)
Run Code Online (Sandbox Code Playgroud)

SQL的目的是从Phrase中删除行,其中PhraseSource表中有更多最近的行.

现在我知道表格Phrase和PhraseSource有相同的列,而Modified包含自1970年以来的秒数,但我无法理解这是如何/为什么这样做或者它在做什么.当我看着它时,似乎在<它只是一列的左侧,在>的右侧,它将是许多行.它甚至没有任何意义吗?

这两个表是相同的,具有以下结构

Id - GUID primary key
... 
... 
...
Modified int
Run Code Online (Sandbox Code Playgroud)

...列包含文本和数字数据约十列.该PhraseSource表可能包含也可能不包含Modified列中具有更高编号的更新行以及不同的文本和数字数据.

Mar*_*und 5

SELECT括号中的语句是子查询或嵌套查询.

会发生的是,对于每一行,将Modified列值与子查询的结果(对于Phrase表中的每一行运行一次)进行比较.

子查询有一个WHERE语句,因此它找到一个与我们当前正在评估的表中ID的行相同的行,Phrase并返回该Modified值(对于一个sigle行,实际上是一个标量值).

比较这两个Modified值,如果Phrase在行之前修改了行PhraseSource,则删除它.

正如您所看到的,这种方法效率不高,因为它要求数据库为表中的每一行运行单独的查询Phrase(尽管我认为某些数据库可能足够智能,可以稍微优化一下).

更好的解决方案

使用效率更高的解决方案INNER JOIN:

DELETE p FROM Phrase p
INNER JOIN PhraseSource ps
  ON p.PhraseId=ps.Id 
WHERE p.Modified < ps.Modified
Run Code Online (Sandbox Code Playgroud)

这应该与您的查询完全相同,但使用有效的JOIN机制.INNER JOIN使用该ON语句选择如何"匹配"两个不同表中的行(由DB非常有效地完成),然后再次比较Modified匹配行的值.

  • 我用我认为可能更有效的解决方案更新了我的答案:-) (2认同)