Reputation: 102
By running this query:
select
c.name, count(s.name) as statecount,
sum(count(ci.name)) OVER() AS citycount
from
countries c, states s, cities ci
where
ci.state_id = s.id
and s.country_id = c.id
group by
s.name
I need to get an output in this style:
Country => statecount => citycount
Upvotes: 1
Views: 25190
Reputation: 35333
Because countries can have multiple states and each state can have multiple cities when you join these 1 to many and 1 to many many your state count is inflated. So you need the distinct count of state. The city count is already unique to country and state, thus doesn't need the distinct. where as state is not unique to country city, thus distinct is needed. This of course assumes you want the count of unique states in each country.
SELECT c.name, count(distinct s.name) as statecount, count(Ci.name) as CityCount
FROM countries c
INNER JOIN states s
on c.id = s.country_ID
INNER JOIN cities ci
ON s.id = ci.state_id
GROUP BY C.name
Or keeping your old style join notation:
SELECT c.name, count(distinct s.name) as statecount, count(ci.name) citycount
FROM countries c,states s,cities ci
WHERE ci.state_id = s.id
and s.country_id = c.id
GROUP BY s.name
Consider the following example: http://rextester.com/ZGYF56786
or pictorially below
See when the joins occur between country, state and city. state gets repeated because of the join to city, making state no longer unique in that column, by doing a distinct we only return a count of 2 states instead of 7, one for each record.
+-----+------------+-------------+
| USA | Illinois | Chicago |
| USA | Illinois | Springfield |
| USA | Illinois | Peoria |
| USA | California | LosAngeles |
| USA | California | Sacramento |
| USA | California | SanDeigo |
| USA | California | Hollywood |
| USA | California | Oakland |
|-----|------------|-------------|
|Name | statecount | Citycount |
| USA | 2 | 7 | <-- Is this result correct? (i hope so)
| USA | 7 | 7 | <-- or this one? (then why bother just count(*) and only 1 count needed.
+-----+------------+-------------+
I would think you want the 1st result since there are only 2 states in USA table listed and 7 cities.
Upvotes: 4
Reputation: 2578
You don't need Over. This should just be a simple group-by.
SELECT c.name, COUNT(s.name) AS statecount, COUNT(ci.name) AS citycount
FROM countries c
JOIN states s
ON c.id = s.country_id
JOIN cities ci
ON s.id = ci.state_id
GROUP BY c.name
Upvotes: 0