使用EXISTS引入子查询

时间:2016-02-29 09:59:53

标签: sql sql-server exists

我有一个很长的查询,当我执行时抛出异常。 查询:

SELECT HostID,HostName,RackID,HostTypeID,DomainName,RackNumberOfHeightUnits,RackStartHeightUnits 
FROM tHosts, tDomains   
WHERE tHosts.DomainID=tDomains.DomainID AND (RackID IN ( SELECT tRacks.Name,tRacks.RackID,tRacks.SiteID,tRacks.Description,NumberOfHeightUnits   
                                                         FROM tDomains, tSites, tRacks   
                                                         WHERE   tDomains.AccountID= tSites.AccountID    
                                                         AND tSites.SiteID = tRacks.SiteID    
                                                         AND tSites.SiteID = 2  
                                                         AND tDomains.AccountID=1 ) 
AND  SiteID IN (SELECT SiteID FROM tSites WHERE SiteID IN (SELECT SiteID FROM tSites WHERE AccountID=1)))AND AccountID=1

这里的查询正在完成:

SELECT tRacks.Name,tRacks.RackID,tRacks.SiteID,tRacks.Description,NumberOfHeightUnits 
                                                         FROM tDomains, tSites, tRacks  
                                                         WHERE tDomains.AccountID= tSites.AccountID  
                                                         AND tSites.SiteID = tRacks.SiteID  
                                                         AND tSites.SiteID = 2  
                                                         AND tDomains.AccountID=1 

**错误:**当EXISTS未引入子查询时,只能在选择列表中指定一个表达式。
  提前完成。

3 个答案:

答案 0 :(得分:2)

使用IN您必须返回一列,即要与之比较的列:

更改此

 ...AND (RackID IN ( SELECT tRacks.Name,tRacks.RackID,tRacks.SiteID,tRacks.Description,NumberOfHeightUnits   
                     FROM tDomains, tSites, tRacks ...

对此:

... AND (RackID IN ( SELECT tRacks.RackID FROM tDomains, tSites, tRacks ...

在这个地方不会使用任何其他栏目"在"

之外

但是 - 说实话 - 整个查询看起来像 - 嗯 - 可改善......

答案 1 :(得分:0)

以下子查询

SELECT SiteID FROM tSites WHERE SiteID IN (SELECT SiteID FROM tSites WHERE AccountID=1)

似乎等于

SELECT SiteID FROM tSites WHERE AccountID = 1

你可以用第二个替换第一个希望摆脱错误

答案 2 :(得分:0)

我认为你应该重新查看你的SQL,并确定你认为你需要以你的方式编写查询的确切原因,不仅仅是为了你在调试它时的理智,还因为你似乎可以简化这个如果对正在发生的事情有更多了解,请查询很多。

从您的SQL看起来您想要给定帐户(ID为1)和网站(ID为2)的所有主机,域和机架详细信息

当您在选择中使用逗号分隔的表格列表编写查询时,它是a)直接更难以阅读和b)更有可能是另一位开发人员后来必须来修改您的查询,第一个选择将被重写为:

SELECT (columns)
FROM tHosts
INNER JOIN tDomains ON tDomains.DomainID = tHosts.DomainID

然后,您想要加入以查找ID为2的网站和ID为1的帐户的机架详细信息。您的tDomains和tSites具有常见的AccountID列,因此您可以加入以下内容:

INNER JOIN tSites ON tSites.AccountID = tDomains.AccountID

并且您的tRack和tSites有一个共同的SiteID列,因此您可以加入这些列:

INNER JOIN tRacks ON tRacks.SiteID = tSites.SiteID

然后,您可以应用where子句将结果过滤到所需的条件:

WHERE tDomains.AccountID = 1
AND tSites.SiteID = 2

您现在有以下查询:

SELECT HostID
     , HostName
     , RackID
     , HostTypeID
     , DomainName
     , RackNumberOfHeightUnits
     , RackStartHeightUnits 
FROM tHosts
INNER JOIN tDomains ON tDomains.DomainID = tHosts.DomainID
INNER JOIN tSites ON tSites.AccountID = tDomains.AccountID
INNER JOIN tRacks ON tRacks.SiteID = tSites.SiteID
WHERE tDomains.AccountID = 1
AND tSites.SiteID = 2

您的SQL中的最后一行似乎是不必要的,因为您再次选择ID为1的帐户的站点ID(并且您已经在内部选择中过滤到了这些机架)。

由于在没有看到表格定义的情况下难以理解您的确切域名,因此可能会遗漏一些内容,但您似乎可以提高可读性,但更重要的是,您可以通过一些更改来提高查询的性能?