Reputation: 7102
I'm trying to get a list of all citizens of a country and list them in a table with 3 rows. The last row shows 'YES' or 'NO' depending on whether or not the person was born in a certain city.
What I did was create two queries: The first query gets all the citizens who were born in the city, and the second query gets all the citizens not born in the city.
Then I just do a UNION.
THe query runs and I think the results look good.
But I was wondering, is this the best way to form a query like this?
Thanks
--all citizens who were born in CityID = 5 who is in the USA
SELECT DISTINCT(CountryCitizenID), Country, 'YES' As Resident
FROM DT_Country_CitizenS dtu
INNER JOIN FT_City fte ON dtu.CountryCitizenID = fte.CitizenID
WHERE cityID = 5
AND Country = 'USA'
UNION
--all Citizens who were not born in CityID = 5 who is in the USA
SELECT DISTINCT(CountryCitizenID), Country, 'NO' As Resident
FROM DT_Country_CitizenS dtu
WHERE NOT EXISTS (
SELECT CitizenID
FROM FT_City fte
WHERE dtu.CountryCitizenID = fte.CitizenID
AND cityID = 5)
AND Country = 'USA'
Upvotes: 0
Views: 102
Reputation: 280252
You shouldn't need a UNION
for this (and generally, when you have two queries that can't possibly intersect, you should use UNION ALL
which avoids a unique sort (or similar operation)). Also, DISTINCT
cannot apply to a single column, as your current query seems to imply. I find it unlikely that there are duplicates in the CountryCitizenID
column, unless it is really poorly named, so I don't think DISTINCT
is needed at all. Finally, what is the point of pulling the Country
column at all, since by definition it will be the same in every row? I've changed it to a constant instead of pulling the actual value (this might prevent a lookup or give a better chance at using a skinnier index), but you shouldn't need that column in the output at all - the application should know that, since the WHERE
clause filters to only rows where Country = 'USA'
, there is no other value possible.
SELECT CountryCitizenID, Country = 'USA', Resident = CASE WHEN EXISTS
(
SELECT 1
FROM dbo.FT_City fte
WHERE fte.CitizenID = dtu.CountryCitizenID
AND fte.cityID = 5
) THEN 'YES' ELSE 'NO' END
FROM dbo.DT_Country_CitizenS AS dtu
WHERE dtu.Country = 'USA';
Upvotes: 5
Reputation: 4934
SELECT CountryCitizenID, Country, CASE WHEN fte.cityID IS NULL THEN 'No' ELSE 'Yes' END As Resident
FROM DT_Country_CitizenS dtu
LEFT JOIN FT_City fte
ON dtu.CountryCitizenID = fte.CitizenID
AND fte.cityID = 5
WHERE Country = 'USA'
Upvotes: 1
Reputation: 23361
Try this:
SELECT DISTINCT(CountryCitizenID),
Country,
case when fte.CitizenID is not null then 'YES' else 'NO' As Resident
FROM DT_Country_CitizenS dtu
LEFT JOIN (select *
from FT_City
where cityID = 5) fte
ON (dtu.CountryCitizenID = fte.CitizenID)
WHERE Country = 'USA'
Upvotes: 2