简体   繁体   English

SQL Server NOT EXISTS效率

[英]SQL Server NOT EXISTS efficiency

I have two tables Card and History with a one-to-many relationship: one card can have one or many histories. 我有两张表CardHistory与一对多的关系:一张卡可以有一个或多个历史。 Card has a CardId column, and History has a CardId and a StatusId column. Card有一个CardId列, History有一个CardId和一个StatusId列。

I want a SQL script which selects the only cards which have no one history with StatusId=310. 我想要一个SQL脚本,它选择唯一没有StatusId = 310的历史记录的卡片。

This is what I've tried. 这就是我尝试过的。

SELECT 
    C.CardId 
FROM 
    Card C
WHERE NOT EXISTS (SELECT * 
                  FROM History H
                  WHERE H.CardId = C.CardId AND H.StatusId = 310)

But I want to know if there is an efficient way. 但我想知道是否有一种有效的方法。

Thanks in advance. 提前致谢。

To answer your question about whether there is a more efficient way: 要回答关于是否有更有效的方式的问题:

Short answer: No, not exists is most likely the most efficient method. 简答:不, not exists很可能是最有效的方法。

Long answer: Aaron Bertrand's article with benchmarks for many different methods of doing the same thing Should I use not in, outer apply, left outer join, except, or not exists? 答案很长:Aaron Bertrand的文章中有许多不同方法做同样事情的基准我应该不使用,外部应用,左外部连接,除了或不存在? Spoiler: not exists wins. 剧透: not exists胜利。

I would stick with your original code using not exists, but Aaron's article has many examples you can adapt to your situation to confirm that nothing else is more efficient. 我会坚持你的原始代码使用不存在,但亚伦的文章有很多例子,你可以适应你的情况,以确认没有其他更有效。

select c.CardId 
  from Card c
  where not exists(
    select 1
      from History h
      where h.CardId=c.CardId 
        and h.StatusId=310
             )

What you're after is called a "negative JOIN". 你所追求的是一种“负面的联合”。 Here's a version without the subquery: 这是没有子查询的版本:

SELECT c.CardId
FROM Card c
LEFT OUTER JOIN History h
  ON h.CardId = c.CardId
  AND h.StatusId = 310
WHERE h.CardId IS NULL;

Your NOT EXISTS method looks reasonable but there is another approach. 您的NOT EXISTS方法看起来很合理,但还有另一种方法。

SELECT *
FROM   Card C
WHERE  EXISTS (SELECT 1
               FROM   history H
               WHERE  H.CardId = C.CardId
               HAVING Count(CASE WHEN H.StatusId = 310 THEN 1 END) = 0) 

Check the performance by running both the queries with your real time data 通过使用实时数据运行这两个查询来检查性能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM