Reputation: 4009
I have a users country table where I hold a list of users country's- a user can have many addresses and therefore many country's
it is joined to the user table via an address table
if I do a select distinct CountryId from UserCountry Data returned is:
1
2
3
4
5
6
etc
If I run the following query I get a User returned
select * from User u join Address a
on u.AddressId = a.Id
where a.CountryId = 1
If I then run
select * from User u join Address a
on u.AddressId = a.Id
where a.CountryId = 2
I get no data returned which is fine. What I need to to do is pass in a list of all the distinct Country Ids and produce a output of which set return a User Object and which set don't return a User object
Upvotes: 0
Views: 115
Reputation: 72175
The following query:
SELECT CountryId, COALESCE(t2.cnt, 0) AS usersPerCountry
FROM (
SELECT DISTINCT CountryId
FROM UserCountry) AS t1
LEFT JOIN (
SELECT a.CountryId, COUNT(*) AS cnt
FROM User u
INNER JOIN Address a ON u.AddressId = a.Id
GROUP BY a.CountryId
) AS t2 ON t1.CountryId = t2.CountryId
ORDER BY COALESCE(t2.cnt, 0) DESC
will give you the number of users associated with each country. If a country is not related to any users at all then 0
is returned.
Explanation:
The above query makes use of two derived tables, t1
and t2
:
t1
, contains a list of all distinct CountryId
values contained in UserCountry
. t2
, returns the number of users per CountryId
. Ids with no users are not returned by this sub-query.Performing a LEFT JOIN
between t1
and t2
with t1
as the first table returns all values of t1
, i.e. all CountryId
values contained in UserCountry
. If there is no match in t2
, then t2.cnt
is NULL
. COALESCE
used in the SELECT
clause converts this NULL
value into a 0
.
Upvotes: 1
Reputation: 6604
This will give you all items in User and Address that do not have a Country entry. Is this what you are looking for?
SELECT *
FROM User U
JOIN Address a
ON a.Id = u.AddressId
WHERE NOT EXISTS
(
SELECT 1
FROM UserCountry uc
WHERE uc.CountryId = a.CountryId
);
For the list of Country
items that do not have a User, you can alternate the statements and find where the CountryId
NOT EXISTS
in the User
and Address
tables
Upvotes: 0