Using the Sakila DB, i am trying to get the Country name, the number of cities that a country have, and the number of addresses of a country
Using the next query i get the country and the cities number
SELECT CO.country,COUNT(CI.city_id)
FROM city CI
INNER JOIN country CO ON CO.country_id = CI.country_id
GROUP BY CO.country;
Using this other one i get the addresses number
SELECT CO.country,COUNT(A.address_id)
FROM city CI
INNER JOIN address A ON A.city_id=CI.city_id
INNER JOIN country CO ON CI.country_id=CO.country_id
GROUP BY CO.country;
I was hinted to use Subqueries to get the desired results, but i can't find how to get all that in one table. Any suggestions?
This is actually a tricky problem. Your join approach can be made to work, with some slight modifications. The total count across each country group will give the number of addresses in that country. But to get the city count for a country, we can count the distinct city names in each country group. The need for DISTINCT here is that the join to the address table will cause each city name to replicated however many times an address appears in a given city. Taking the distinct city count gets around this problem.
SELECT
co.country_id,
COUNT(DISTINCT ci.city_id) AS city_cnt,
COUNT(a.city_id) AS address_cnt
FROM country co
INNER JOIN city ci
ON co.country_id = ci.country_id
INNER JOIN address a
ON ci.city_id = a.city_id
GROUP BY
co.country_id;
You can achieve the result using below sub query. This is basically to show how you can write it. Its recommended to use join(Refer answer from Tim Biegeleisen) than Sub queries as it gives good performance.
select
Co.Country,
(Select COUNT(1) from City Ci where Ci.countryid=co.countryid) CityCount,
(Select COUNT(1) from Address A Join city c on a.city_id=c.city_id where C.countryid=co.countryid) AddressCount
From Country Co
Related
Hello I started using MySQL and I seem to be having trouble trying to nest formulas. I'm working on a problem and the question is, What country has the most cities?
I have two tables:
CITY:
city
city_id
country_id
COUNTRY:
country
country_id
I am able to join the two tables together to get the cities to match with the countries but after that I don't know how to count to the country that has the most cities.
My current code is:
SELECT city.city, country.country
FROM city, country
WHERE city.country_id = country.country_id
From there I don't know how to add a count function without it coming back as as error. I dont fully understand the basics of nesting.
Thank you, any help is appreciated.
You do not need to do nesting necessarily. To simply know, which country has most number of cities, just use group by:
select country_id, count(1)
from city
group by country_id
This will give you the number of cities in each country. Then you could use a CTE to get the country with the largest number of cities.
You need to GROUP BY if you want to use aggregate functions.
Given the fact that you're very new to this I think you'll get a lot more out of this if you spend a few minutes reading up on some documentation. Don't worry, this is easy stuff so you'll understand this in no time. Please have a look at the following basic info (MySQL GROUP BY basic info) regarding the use of GROUP BY in MySQL. Your questions are answered in the topic regarding 'MySQL GROUP BY with aggregate functions'.
Basic group by:
SELECT
status, COUNT(*)
FROM
orders
GROUP BY status;
Group by using a join:
SELECT
status, SUM(quantityOrdered * priceEach) AS amount
FROM
orders
INNER JOIN
orderdetails USING (orderNumber)
GROUP BY status;
SELECT x.country
FROM country x
JOIN city y
ON y.country_id = x.country_id
GROUP
BY x.country
ORDER
BY COUNT(*) DESC LIMIT 1;
On the (fantastically unlikely) chance that the most civilised countries have equal numbers of cities, you would have to amend this a little.
What makes this difficult is possible ties, i.e. two or more countries sharing the maximum number of cities. As of MySQL 8 you can use window functions to help you with this. Here I compare the country counts and their maximum and then pick the rows were the two match.
select *
from country
where (country_id, true) in -- true means it is a maximum city country
(
select country_id, count(*) = max(count(*)) over()
from city
group by country_id
);
Sorry it was my first post, my code looks terrible.
following my code again.
select
country.country_id,
count(city.city_id)
from
country
inner join
city
on
city.country_id=country.country_id
group by
city.country_id
having
count(city.city_id) =
(SELECT
max(count(city.city_id))
FROM
city
GROUP BY
city.city_id);
Best regards,
Jens
Try the following code:
**select
country.country_id,
count(city.city_id)
from
country
inner join
city
on
city.country_id=country.country_id
group by
city.country_id
having
count(city.city_id) =
(SELECT
max(count(city.city_id))
FROM
city
GROUP BY
city.city_id);**
You need to group by country_id to make sure all cities that are connected to one country_id can be counted.
Where is a good approach, however it does not work together with "group by" as it will be accounted before the "group by" command.
The way you joined your data from different tables is not a very proper yet working way. I suggest to use the inner join in this case to make the command more obvious/better readable.
Count() is used to count the number of cities that accumulate on one country
max() is used to get the country with the most cities (highest count()).
SELECT country_id, count(1)
FROM city
GROUP BY country_id
ORDER BY count(1) desc;
Try following Code -
SELECT *,
(SELECT COUNT(*) FROM cities WHERE cities.country_id=C.country_id) as cities_count
FROM country C
ORDER BY cities_count DESC
LIMIT 0,1
Also is joining the two tables necessary? In your query, you said you need to find What country has the most cities?
Above query will only return one country with max cities.
You can find the country like this:
SELECT MAX(c.id) FROM (SELECT COUNT(id) AS id
FROM city group by country_id) c
I want to write a query that can show the amount of purchases made in the month of June, grouped by city. So I wrote this query:
SELECT state, city, COUNT(*)
FROM address
JOIN person
JOIN purchase
WHERE purchase.person_FK = person.id
AND address.person_FK = person.id
AND MONTH(purchase.purchase_date) = 5
GROUP BY state, city
ORDER BY state, city;
But this query doesn't return the cities that have no purchases in that month, and I want to show them. Can you help me?
You need a city table with all the cities, then do a LEFT JOIN.
And put the JOIN condition on the ON section not the WHERE
SELECT Cities.state, Cities.city, COUNT(*)
FROM Cities
LEFT JOIN Purchase
ON Cities.city = Purchase.city
AND Cities.state = Cities.state
JOIN person
ON purchase.person_FK = person.id
AND MONTH(purchase.purchase_date) = 5
JOIN address
ON address.person_FK = person.id
GROUP BY Cities.state, Cities.city
ORDER BY Citiesstate, Cities.city;
Look at your joins, 'JOIN' is the same as 'INNER JOIN' which only shows results which is in both tables, you'll need to use a LEFT or FULL join to get what you need.
Theres a diagram here which explains them well
You will need to have a table that provides a listing of all cities you want to show (if you don't already have that). Then you join to the city table as well. Otherwise, your query has no idea which cities to show with a zero count. In addition, you will need to change your JOIN's to LEFT JOIN's
SELECT city.state, city.city, COUNT(*)
FROM address
LEFT JOIN person ON person.id = address.person_FK
LEFT JOIN purchase ON purchase.person_FK = person.id
LEFT JOIN city ON purchase.city = city.city
WHERE MONTH(purchase.purchase_date) = 5
GROUP BY address.state, address.city
ORDER BY address.state, address.city;
I'm trying to get the city name for my drop down list but using INNER JOIN and mysql but I end up getting no result, Please help me identify the issue. Thanks so much in advance.
SELECT city_name
from cities
INNER JOIN states
ON cities.city_id = states.state_id
GROUP BY cities.city_name
and here is my cities table database
and here is my states table databse
Your query should be:
SELECT city_name
from cities
INNER JOIN states
ON cities.state_id = states.state_id
GROUP BY cities.city_name
You are matching city_id with State_Id which wouldn't fetch you anything
I'm trying to query the sum of the populations of all cities where the CONTINENT is 'Asia'.
The two tables CITY and COUNTRY are as follows,
city - id, countrycode, name population
country - code, name, continent, population
Here's my query
SELECT SUM(POPULATION) FROM COUNTRY CITY
JOIN ON COUNTRY.CODE = CITY.COUNTRYCODE
WHERE CONTINENT = "Asia";
This doesn't work. What am I doing wrong. I'm new to SQL.
It isn't working because the way you've written it CITY is being interpreted as a table alias for COUNTRY. Additionally, it looks like you've got a POPULATION column in each table so you need to disambiguate it. Let me rewrite the query for you:
SELECT SUM(CITY.POPULATION)
FROM COUNTRY
JOIN CITY
ON COUNTRY.CODE = CITY.COUNTRYCODE
WHERE COUNTRY.CONTINENT = "Asia";
I know the question was already answered, but I would like to put out the optimised solution. The below solution will decrease the execution time and at the same time it will take less resource to perform the SQL query.
select sum(a.population) from city a
inner join(select * from country where continent = 'Asia') b
on a.countrycode=b.code;
I would like to explain a bit on top of that, as you see I'm applying the filter condition before performing Join operation. So during reshuffling phase, the data would be very less and this way query will take less time to execute. You will not see a drastic performance changes in less data size, however while running this queries in large dataset, you can see the performance improvement.
The JOIN needs to go between the two table names:
SELECT SUM(CITY.POPULATION) FROM COUNTRY INNER JOIN CITY
ON COUNTRY.CODE = CITY.COUNTRYCODE
WHERE CONTINENT = "Asia";
MySQL JOIN syntax manual
SELECT SUM(COUNTRY.POPULATION)
FROM COUNTRY
JOIN CITY
ON COUNTRY.CODE = CITY.COUNTRYCODE
WHERE CONTINENT = "Asia";
SELECT SUM(CITY.POPULATION)
FROM CITY
INNER JOIN COUNTRY ON CITY.COUNTRYCODE = COUNTRY.Code
where COUNTRY.CONTINENT = 'Asia';
Line 3 has INNER JOIN because there is one column in both the tables that are common to both
SELECT sum(city.population) FROM city LEFT JOIN country ON city.countrycode=country.code
WHERE country.continent='Asia'
You can run the following code using Oracle.
SELECT SUM(c.POPULATION)
FROM CITY c
INNER JOIN COUNTRY co ON c.CountryCode = co.Code
WHERE CONTINENT ='Asia' ;
select SUM(cty.POPULATION) from COUNTRY cntry, CITY cty where cty.COUNTRYCODE=cntry.CODE AND cntry.CONTINENT='Asia';
select sum(S.Population)
from City S
where S.CountryCode in (select Code
from Country C
where CONTINENT = 'Asia');
I need to query the database by joining two tables. Here is what I have:
Table Town:
id
name
region
Table Supplier:
id
name
town_id
I currently have the following query which outputs all the Towns that belong to a given region:
SELECT id, name FROM Town WHERE region = 'North West';
Now I need to extend this query and create two further queries as follows:
Output the number of Suppliers for each Town
Output only the Towns that have 1 or more Supplier
I am using PHP for my scripts if that helps. I know I may be able to to get this data using PHP but in terms of performance it will probably be better if it is done in MySQL.
EDIT (27/07/10):
I now needs to extend this one last time - there is another table called Supplier_vehicles:
id
supplier_id
vehicle_id
A Supplier can have many Supplier_vehicles. The count (NumSupplier in this case) needs to now contain the total number of suppliers in a given town that have any of the given vehicle_id (IN condition):
SELECT * FROM Supplier s, Supplier_vehicles v WHERE s.id = v.supplier_id AND v.vehicle_id IN (1, 4, 6)
Need to integrate the above query into the existing JOIN query.
Count the number of suppliers.
SELECT t.id, t.name, count(s.id) as NumSupplier
FROM Town t
LEFT OUTER JOIN Suppliers s ON s.town_id = t.id
GROUP BY t.id, t.name
Only towns that have at least one supplier
SELECT DISTINCT t.id, t.name
FROM Town t
INNER JOIN Suppliers s ON s.town_id = t.id
And you are 100% correct, the best place for this is an SQL query.
SELECT t.id, t.name, count(s.id) as NumSupplier
FROM Town t
LEFT JOIN Suppliers s
[WHERE NumSupplier > 1]
GROUP BY t.id