存在/不存在:“选择 1”与“选择字段”

Posted

技术标签:

【中文标题】存在/不存在:“选择 1”与“选择字段”【英文标题】:Exists / not exists: 'select 1' vs 'select field' 【发布时间】: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 中的优化器已经足够成熟,可以理解所有需要子查询是一个布尔值。

【问题讨论】:

没有区别,都是一样的。检查两个查询的执行计划以进行验证。 看看这个答案..***.com/a/6140367/2975396 【参考方案1】:

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

根据MSDN,exists

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

还有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' 而意外失败,或者通过简单地计时添加更多列的效果或查看调试器***.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 ..." 是模式绑定对象中不允许使用 "*" —— 它会抛出:

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

【讨论】:

以上是关于存在/不存在:“选择 1”与“选择字段”的主要内容,如果未能解决你的问题,请参考以下文章

不存在与不存在

不存在与不存在[重复]

问题存在与认知---问题产生的原因是对存在的不完全或错误认知

优化存在与不存在

为啥我的 PrimeNG FileUpload 组件存在这个问题,该组件与引用不存在的页面的 url 参数相关

php Popuplate使用数据库中存在的所有可用重力形式的ACF选择字段命名为“gravityform”。