Reputation:
I Have a long query which is throwing an exception when i execute. Query:
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
It is accomplishing for the query in here:
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
**The error: ** Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
Thanx in advance.
Upvotes: 3
Views: 2424
Reputation: 1599
I think you should re-look at your SQL and determine exactly why you think you need to write the query in the way you have, not only for your own sanity when debugging it, but because it seems that you could simplify this query a great deal if there was a little more understanding of what was going on.
From your SQL it seems like you want all host, domain and rack details for a given account (with ID 1) and site (with ID 2)
When you write your query with a comma seperated list of tables in your select, it's a) straight away more diffcult to read and b) more likely to another developer later down the line who has to come and amend your query, your first select would be re-written as:
SELECT (columns)
FROM tHosts
INNER JOIN tDomains ON tDomains.DomainID = tHosts.DomainID
You then want to join to find the rack details for the site with ID 2 and account with ID 1. Your tDomains and tSites have common AccountID columns, so you can join on those:
INNER JOIN tSites ON tSites.AccountID = tDomains.AccountID
and your tRacks and tSites have a common SiteID column so you can join on those:
INNER JOIN tRacks ON tRacks.SiteID = tSites.SiteID
you can then apply your where clause to filter the results down to your required criteria:
WHERE tDomains.AccountID = 1
AND tSites.SiteID = 2
You now have the following query:
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
The final line in your SQL seems unnecessary, as you are selecting the site ids for the account with ID 1 again (and you've already filtered to those racks anyway in your inner select).
There may be something missing from this, as its hard to understand your exact domain without seeing the table definitions, but it seems likely you can improve the readability but more importantly the performance of your query with a few changes?
Upvotes: 0
Reputation: 6622
Following sub-query
SELECT SiteID FROM tSites WHERE SiteID IN (SELECT SiteID FROM tSites WHERE AccountID=1)
seems to be equal to
SELECT SiteID FROM tSites WHERE AccountID = 1
You can replace first one with second hoping to get rid of the error
Upvotes: 0
Reputation: 67321
With IN
You must return one column, the column you want to compare against:
Change this
...AND (RackID IN ( SELECT tRacks.Name,tRacks.RackID,tRacks.SiteID,tRacks.Description,NumberOfHeightUnits
FROM tDomains, tSites, tRacks ...
To this:
... AND (RackID IN ( SELECT tRacks.RackID FROM tDomains, tSites, tRacks ...
In this place no other column will be used "outside"
But - to be honest - the whole query looks like - uhm - improveable ...
Upvotes: 2