介绍使用EXISTS的子查询

3

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

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 时,只能在选择列表中指定一个表达式。
提前致谢。


AND (RackID IN ( SELECT tRacks.Name,tRacks.RackID,tRacks.SiteID,tRacks.Description,NumberOfHeightUnits 更改为 AND (RackID IN ( SELECT tRacks.RackID - artm
1
第一条建议:使用显式的 join 语法。@artm 是正确的,但看起来您还需要从 tRacks 中获取数据,因此您应该将其与外部查询进行 join。此外,这不是一个长查询,实际上相当短。 - HoneyBadger
3个回答

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 ...

在这个地方不会使用“外部”的任何其他列。
但是,说实话,整个查询看起来还有改进的余地...

0

以下是子查询

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

似乎等于

SELECT SiteID FROM tSites WHERE AccountID = 1

您可以将第一个替换为第二个,以期消除错误。

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

而且你的tRacks和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(并且你已经在内部选择中过滤了这些机架)。

如果没有看到表定义,很可能会有遗漏,但通过一些更改,你可以提高查询的可读性和性能。


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