【问题标题】:Difference between NOT IN and equals vs. IN and not equalsNOT IN 和 equals 与 IN 和 not equals 的区别
【发布时间】:2013-04-18 15:52:19
【问题描述】:

我的查询需要返回所有流水线速率不是“No Usage”的使用记录。

What's the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL?

我已经看到上述问题并决定使用 IN 而不是 EXISTS,因为表中的值可以为空。以下哪一种更好,更有效,或者有没有其他方法比以下两种更有效?

SELECT *
FROM   usagerecords UR
WHERE  UR.usagerateid NOT IN (SELECT id
                              FROM   pipelinerate PR
                              WHERE  PR.name = 'No Usage')

SELECT *
FROM   usagerecords UR
WHERE  UR.usagerateid IN (SELECT id
                          FROM   pipelinerate PR
                          WHERE  PR.name <> 'No Usage') 

【问题讨论】:

  • 比较执行计划,你就会找到答案。
  • 这两个查询甚至不等价。为什么要比较效率?
  • 同意@ypercube。在开始担心性能之前,请确保您的查询具有相同的语义并产生相同(正确)的结果。

标签: sql sql-server


【解决方案1】:

NOT IN 如果id 可以为空(我希望它不是,否则它的名字很糟糕)会给你错误的结果。

既然已经一次又一次地证明EXISTS 效率更高(或至少效率不低),为什么你会选择IN 而不是EXISTS,因为它可以短路? IN 必须实现整个集合。

SELECT * -- stop doing this
  FROM dbo.usagerecords AS UR
  WHERE EXISTS
  (
    SELECT 1 FROM dbo.pipelinerate AS pr
      WHERE pr.id = ur.usagerateid
      AND pr.name <> 'No Usage'
  );

你也可以这样表达你的其他查询:

SELECT * -- again, stop doing this
  FROM dbo.usagerecords AS UR
  WHERE NOT EXISTS 
  (
    SELECT 1 FROM dbo.pipelinerate AS pr
      WHERE pr.id = ur.usagerateid
      AND pr.name = 'No Usage'
  );

但我不知道哪个会得到正确的结果。这就是我们通常要求提供样本数据和所需结果的原因。

您使用SELECT * 可能比使用INEXISTS 对性能产生更大的负面影响。 FWIW。

【讨论】:

  • 此查询是较大查询的一部分,我没有使用 SELECT * 我只是为了简化而提到它,并且 id 不可为空。我已经厌倦了EXISTSIN。我在使用 EXISTS 时得到了不必要的记录,但在使用 IN 时得到了正确的记录
  • @Srikanth 显示示例数据和所需结果。否则我们只是猜测。
  • 在尝试EXISTS 时,我写了pr.id &lt;&gt; ur.usagerateid AND pr.name &lt;&gt; 'No Usage' 而不是pr.id = ur.usagerateid AND pr.name &lt;&gt; 'No Usage'。谢谢它的工作原理并且速度更快。你会推荐哪一个NOT EXISTSEXISTS
  • 嗯,这取决于!他们都给出了正确的结果吗?你测试过吗?你知道你期待什么结果吗?
  • 是的,两者都给出了正确和预期的结果。两者平均花费相同的时间,并且执行计划相似。
【解决方案2】:

“NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL有什么区别?”

Not exists 一看到匹配就退出。

不在不。人们会在包含大量结果的列表中关注或不关注,但 Jeff Moden 的一些测试表明,它们在高达百万个项目范围内都能正常工作,这通常就足够了。

left join where is null 是基于设置的,所以它是“经典”的解决方案。 “在”基本上变成了一个巨人或列表。当您只是在测试遗漏的东西时,左连接 where is null 没有任何特定优势,我喜欢在寻找每个用户的最新事件时使用左自连接/为 null 模式。

Not in 超级简单,任何新手开发者都会明白它的作用。

不存在几乎一样清楚,但可能高于新手。

Left join/is null 经常被中级开发人员误解。所以我个人发现不是最可维护的。

【讨论】:

  • 不管Moden的测试如何,为什么当你知道你的数据很小时用一种方式编码,当你知道你的数据很大时用另一种方式(但并不难编码)?当你的数据变大时,你会去改变你所有的代码吗?如果您不知道您的数据是否/何时变大怎么办?标准原则适用于此:始终使用最有效的方法。
  • 另外,虽然这个“问题”已在原始帖子中列出,但它只是一个参考链接,并不是 OP 实际提出的问题。
  • Jeff Moden 测试可能是特定于 RDBMS 的。我的不科学观察是,“不在”非常慢,使用红砖数据库的阈值要低得多。
  • "下面哪一种更好更高效,或者有没有比下面两种更有效的方法?" - 非常主观。我将“更好”定义为中级及以下开发人员更容易理解。在大多数情况下,开发人员花费的时间比数据库花费的时间要多,而且 bug 的成本高得令人难以置信。
  • 我主要在 sqlservercentral 上阅读 Moden,所以它可能只是指 sql server。写一个标准的方式很好。应避免预优化。致力于查询优化器的开发人员做了很多工作来减轻开发人员所做的常见愚蠢事情
猜你喜欢
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-22
  • 2017-12-01
  • 2011-03-29
相关资源
最近更新 更多