SQL Server 查询:SELECT 1 WHERE EXISTS vs SELECT TOP 1 1

Posted

技术标签:

【中文标题】SQL Server 查询:SELECT 1 WHERE EXISTS vs SELECT TOP 1 1【英文标题】:SQL Server query : SELECT 1 WHERE EXISTS versus SELECT TOP 1 1 【发布时间】:2010-01-19 05:41:15 【问题描述】:

我需要提供一个标志 - 如果条件不满足,则为 0,如果条件满足,则为 1 - 我可以通过两种不同的方式来做到这一点:

获取员工 ID、姓名,如果子订单中有其他人,则为 1 - 如果没有,则为 0:

SELECT e.ID
     , e.Name
     , ISNULL ( ( SELECT TOP 1 1 FROM Employee se WHERE se.ManagerID = e.ID ) , 0 ) AS HasSubordinates 
  FROM Employee e

SELECT e.ID
     , e.Name
     , ISNULL ( ( SELECT 1 WHERE EXISTS ( SELECT * FROM Employee se WHERE se.ManagerID = e.ID ) ) , 0 ) AS HasSubordinates 
  FROM Employee e

您会选择哪个版本以及为什么?

更新 1

这个怎么样?

SELECT o.ID
     , o.Name
     , o.StartDate
     , o.EndDate
     , ISNULL ( ( SELECT TOP 1 1 FROM changes c WHERE c.ChangeDate BETWEEN o.StartDate AND o.EndDate ) , 0 ) AS IsChanged
  FROM Orders o

SELECT o.ID
     , o.Name
     , o.StartDate
     , o.EndDate
     , ISNULL ( ( SELECT 1 WHERE EXISTS ( SELECT * FROM changes c WHERE c.ChangeDate BETWEEN o.StartDate AND o.EndDate ) ), 0 ) AS IsChanged
  FROM Orders o

【问题讨论】:

感谢 OMG Ponies 的快速回答。我将验证正确的。顺便说一句:你在 *** 上花了多少时间 - 我看到你很活跃 :) 更新将为所有行返回相同的值。这是对那些已经通过更改标准提供答案的人的不尊重。 【参考方案1】:

都不是,我会使用:

   SELECT t.id,
          t.name,
          CASE WHEN x.managerid IS NULL THEN 0 ELSE 1 END AS HasSubordinates 
     FROM EMPLOYEE t
LEFT JOIN (SELECT DISTINCT 
                  e.managerid
             FROM EMPLOYEE e) x ON x.managerid = t.id

...因为 SELECT 子句中的相关 SELECTS 不好 - 它们无法扩展,因为它们针对返回的每一行执行。这意味着您拥有的行越多,相关的 SELECT 将被调用的次数越多。

【讨论】:

' 打败了我!这绝对是要走的路! +1! 在发布这个问题后,我正在查看另一个 OMG Ponies 的问题 (***.com/questions/1590208) - 为什么是 DISTINCT 而不是 分组方式 ? @MiniMe:因为它不使用聚合函数。 GROUP BY e.managerid 是等效的,并且会执行相同的操作。【参考方案2】:

我也不会...

原因是(据我所知)当您在 select 语句中有一个子选择时,该子选择将对返回的每一行执行一次。因此,如果您有 100 行由主查询返回,您实际上将运行 101 个查询。当您使用连接时,您只执行一个需要将左右匹配在一起的查询。请注意,如果您在 ManagerId 上有一个索引会有所帮助。

试试这样的:

SELECT e.ID,
       e.Name,
       COUNT(se.ID) AS TotalStaff
FROM    Employee e 
        LEFT JOIN Employee se 
                ON se.ManagerID = e.ID
GROUP BY e.ID, e.Name 

这与您所拥有的略有不同,因为我返回的是总数,而不仅仅是 0|1,但如果您需要 1|0,这很容易更改...

如果这有帮助,请告诉我

【讨论】:

COUNT(se.ID)遍历LEFT JOIN 表中的所有行我试图避免这种情况,只需选择符合我的条件的第一个 - 或使用 EXISTS。

以上是关于SQL Server 查询:SELECT 1 WHERE EXISTS vs SELECT TOP 1 1的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server ---T-SQl基本语句

创建一个存储过程,给定某学生学号,要求查询出该学生的姓名,所选课程名和成绩.(SQL SERVER)

SQL Server 分页

SQL Server 查询:SELECT 1 WHERE EXISTS vs SELECT TOP 1 1

SQL Server 数据库的SELECT 语句基本用法介绍

带有 TIMESTAMP 的 SQL Server 中的表连接问题