使用T-SQL EXCEPT和DELETE /优化查询

时间:2017-03-31 14:39:06

标签: sql sql-server-2008 tsql query-optimization

以下代码从表中删除与非活动项目相关的任务记录。

delete from [Deliverables] where 
[Deliverables].[ProjectID] not in 
(
select 
[ProjectID] from [ActiveProjects]
)

我在某处读过,使用带有子查询的NOT IN返回很多值并不是最有效的事情,最好使用EXCEPT子句。

但是,当我尝试使用以下代码时,我收到错误(关键字'除'之外的语法不正确。)

delete from [Deliverables]
except
select * from [Deliverables], [ActiveProjects]
where [Deliverables].[ProjectID] = [ActiveProjects].[ProjectID]

如何将EXCEPTDELETE一起使用?如果我不能,有没有办法优化我的查询以更快地执行?

3 个答案:

答案 0 :(得分:4)

你可以尝试not exists,脚本看起来像:

delete from [Deliverables] 
where not exists 
    (select 1 
        from [ActiveProjects]
        where [ActiveProjects].[ProjectID] = [Deliverables].[ProjectID])

如果[ActiveProjects]中有大量数据,那么它应该是更好的解决方案,但它是所有数据依赖的,所以请在使用前测试效率。

答案 1 :(得分:1)

delete d
from [Deliverables] as d
    inner join (
        select d2.[ProjectId] from [Deliverables] as d2
        EXCEPT
        select ap.[ProjectId] from [ActiveProjects] as ap
    } as todel on
        ((todel.[ProjectId] is NULL) and (d.[ProjectId] is NULL))
        or todel.[ProjectId] = d.[ProjectId]

一个微妙之处:EXCEPT的优点是它将等同于NULL值,而不是确定它们永远不匹配(就像“ =”一样)。在您的琐碎示例(仅查看id)中,这不太可能有价值,但是,如果您要比较允许null的表的较大部分,则必须考虑这种尴尬的“ null匹配”,否则会遗漏很多行。

答案 2 :(得分:0)

尝试这样(通过添加where-clauses和列名等来修改您的需求)

delete from table1
  from table1 a
 inner join
      ( select your_column
          from table1
        except
        select your_column
          from table2
      ) b
    on a.your_column = b.your_column;