SQL中EXISTS和IN的区别是什么?

505

EXISTSIN在SQL中有何区别?

何时应使用EXISTS,何时应使用IN

22个回答

3

哪种方式更快取决于内部查询获取的查询数:

  • 当您的内部查询获取数千行时,则使用EXIST会是更好的选择
  • 当您的内部查询获取少量行时,IN会更快

EXIST评估为真或假,但IN比较多个值。当您不知道记录是否存在时,请选择EXIST。


3
原因在于EXISTS运算符基于“至少找到”原则工作。一旦找到至少一个匹配行,它就会返回true并停止扫描表。
另一方面,当IN运算符与子查询结合使用时,MySQL必须先处理子查询,然后使用子查询的结果来处理整个查询。
经验法则是,如果子查询包含大量数据,则EXISTS运算符提供更好的性能。然而,如果从子查询返回的结果集非常小,则使用IN运算符的查询将执行得更快。

3
根据我的了解,当子查询返回一个NULL值时,整个语句就会变成NULL。在这种情况下,我们使用EXISTS关键字。如果我们想比较子查询中的特定值,则使用IN关键字。

1
我的理解是,只要我们不涉及NULL值,两者应该是相同的。
查询为什么不返回“= NULL”和“is NULL”的值,原因是相同的。请参考此链接:http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/ 就布尔值与比较器参数而言,为生成布尔值,需要比较两个值,这也是任何if条件语句的工作原理。因此,我无法理解IN和EXISTS之间的区别。

1

2
需要注意的是,即使在2017年发布此答案时,您所涉及的Oracle产品已经发布了12年,并且已经超过其生命周期。 - Caius Jard

0

如果你可以使用where in代替where exists,那么where in可能更快。

使用where inwhere exists将遍历父结果的所有结果。区别在于,where exists会导致大量的依赖子查询。如果你可以避免依赖子查询,那么where in将是更好的选择。

例子

假设我们有10,000家公司,每家公司有10个用户(因此我们的用户表有100,000条记录)。现在假设你想通过他的名字或公司名找到一个用户。

以下使用were exists的查询执行时间为141毫秒:

select * from `users` 
where `first_name` ='gates' 
or exists 
(
  select * from `companies` 
  where `users`.`company_id` = `companies`.`id`
  and `name` = 'gates'
)

这是因为对于每个用户,都会执行一个依赖子查询: enter image description here 但是,如果我们避免使用exists查询并改用:
select * from `users` 
where `first_name` ='gates' 
or users.company_id in  
(
    select id from `companies` 
    where  `name` = 'gates'
)

那么,避免了依赖子查询,查询运行时间为0.012毫秒

enter image description here


0

如果子查询返回多个值,则可能需要执行外部查询-如果条件中指定的列中的值与子查询结果集中的任何值匹配。要执行此任务,您需要使用in关键字。

您可以使用子查询来检查是否存在一组记录。为此,您需要使用带有子查询的exists子句。 exists关键字始终返回true或false值。


0

我相信这个问题有一个简单明了的答案。为什么不从开发那个函数的人那里查一下呢?

如果你是 MS SQL 开发人员,这里是直接来自 Microsoft 的答案。

IN:

确定指定的值是否与子查询或列表中的任何值匹配。

EXISTS:

指定一个子查询来测试行的存在性。


0

我发现在编程中使用 EXISTS 关键字通常非常慢(在 Microsoft Access 中很明显)。相反,我会以这种方式使用连接运算符: should-i-use-the-keyword-exists-in-sql


0

我对最近使用的一个查询进行了一些练习。我最初使用INNER JOIN创建了它,但我想看看用EXISTS会是什么样子/效果如何。我进行了转换。我将在此处包含两个版本以供比较。

SELECT DISTINCT Category, Name, Description 
FROM [CodeSets] 
WHERE Category NOT IN (
    SELECT def.Category
      FROM [Fields] f
      INNER JOIN [DataEntryFields] def ON f.DataEntryFieldId = def.Id
      INNER JOIN Section s ON f.SectionId = s.Id
      INNER JOIN Template t ON s.Template_Id = t.Id
    WHERE t.AgencyId = (SELECT Id FROM Agencies WHERE Name = 'Some Agency')
        AND def.Category NOT IN ('OFFLIST', 'AGENCYLIST', 'RELTO_UNIT', 'HOSPITALS', 'EMS', 'TOWCOMPANY', 'UIC', 'RPTAGENCY', 'REP')
        AND (t.Name like '% OH %') 
        AND (def.Category IS NOT NULL AND def.Category <> '')
)
ORDER BY 1

以下是统计数据: 输入图片描述

这是转换后的版本:

SELECT DISTINCT cs.Category, Name, Description 
FROM [CodeSets] cs
WHERE NOT Exists (
    SELECT * FROM [Fields] f
      WHERE EXISTS (SELECT * FROM [DataEntryFields] def 
                       WHERE def.Id  = f.DataEntryFieldId
                           AND def.Category NOT IN ('OFFLIST', 'AGENCYLIST', 'RELTO_UNIT', 'HOSPITALS', 'EMS', 'TOWCOMPANY', 'UIC', 'RPTAGENCY', 'REP')
                           AND (def.Category IS NOT NULL AND def.Category <> '')
                           AND def.Category = cs.Category
                           AND EXISTS (SELECT * FROM Section s 
                                          WHERE f.SectionId = s.Id
                                          AND EXISTS (SELECT * FROM Template t 
                                                        WHERE s.Template_Id = t.Id
                                                           AND EXISTS (SELECT * FROM Agencies 
                                                                          WHERE Name = 'Some Agency' and t.AgencyId = Id)
                                                                             AND (t.Name like '% OH %')
                                                    )
                                        )
                    )
)
ORDER BY 1

结果对我来说并不令人印象深刻。 输入图像说明 如果我对SQL的工作原理更了解,我可以给你一个答案,但是你可以从这个例子中得出自己的结论。
INNER JOIN和IN()更容易阅读。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接