【问题标题】:Exists / not exists: 'select 1' vs 'select field'存在/不存在:“选择 1”与“选择字段”
【发布时间】:2014-12-15 05:05:35
【问题描述】:

两者中哪一个会更好(我最近被指责不小心我的代码,因为我在 Oracle 中使用了后者):

Select * 
from Tab1
Where (not) exists(Select 1 From Tab2 Where Tab1.id = Tab2.id)


Select * 
from Tab1
Where (not) exists(Select Field1 From Tab2 Where Tab1.id = Tab2.id)

还是两者都一样?

请从 SQL Server 和 Oracle 的角度回答。

我已经用谷歌搜索(主要来自 sql-server 端)并发现对此仍有很多争论,尽管我目前的观点/假设是 RDMBS 中的优化器已经足够成熟,可以理解所有需要子查询是一个布尔值。

【问题讨论】:

标签: sql sql-server oracle exists


【解决方案1】:

是的,它们是一样的。 exists 检查子查询中是否至少有一行。如果是,则计算结果为true。子查询中的列无论如何都无关紧要。

根据MSDNexists

指定一个子查询来测试行是否存在。

还有Oracle

EXISTS 条件测试子查询中是否存在行。

也许MySQL documentation 更能说明问题:

传统上,EXISTS 子查询以 SELECT * 开头,但它可以以 SELECT 5 或 SELECT column1 或任何其他开头。 MySQL 会忽略此类子查询中的 SELECT 列表,因此没有区别。

【讨论】:

  • Postgres 有什么不同吗?
  • 我不知道。我没有使用 Postegres 的经验。
  • PostgreSQL 也是一样的。你也可以选择 null 作为其他任何东西。
【解决方案2】:

我知道这是旧的,但想补充我最近观察到的几点..

即使exists只检查存在,当我们写“select *”时,列会被扩展,除了这个轻微的开销,没有区别。

来源:
http://www.sqlskills.com/blogs/conor/exists-subqueries-select-1-vs-select/

更新:
我提到的文章似乎无效。即使我们写select 1,SQLServer 也会扩展所有列..

在使用各种方法时,请参考下面的链接进行深入分析和性能统计..

Subquery using Exists 1 or Exists *

【讨论】:

  • Conor 的文章确实有错误。他建议SELECT * 将扩展所有列元数据,而SELECT 1 不会。然而,他们俩实际上都是这样做的。您可以通过拒绝对列的权限并运行SELECT 1 WHERE EXISTS (SELECT 1 FROM T); 来查看这一点,这可能会因The SELECT permission was denied on the column 'Foo' 而意外失败,或者通过简单地计时添加更多列的效果或查看调试器stackoverflow.com/a/6140367/73226
  • @MartinSmith:非常感谢,我很久以前就读过你的回答,但有些东西错过了一些东西。再次感谢您揭穿这个神话
【解决方案3】:

子查询的列列表中的表达式完全无关紧要,它甚至不会被执行:

select * from dual t1
where exists (
    select 1/0 from dual t2
         --^^^ division by 0  
    where t2.dummy = t2.dummy)
/

DUMMY
--------
X

【讨论】:

    【解决方案4】:

    根据我的使用经验,唯一需要注意的是 "EXISTS(SELECT * ..." 和 "EXISTS(SELECT 1 ..." 是模式绑定对象中不允许使用 "*" —— 它会抛出:

    模式绑定对象中不允许使用语法“*”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-16
      • 2021-07-27
      • 2015-12-07
      • 2020-12-14
      • 2013-02-06
      • 2021-10-21
      • 2021-07-02
      • 1970-01-01
      相关资源
      最近更新 更多