SQL, choosing maximum values from another table - sql

This one I've been spending the last hours on. Still haven't found an answer so I figured I'd ask.
I have two tables:
Country - Code, Name, Populaion.
City - CountryCode, Name, Population.
The Foreign key is the CountryCode which response to country.Code.
I'm trying to find the most populated city in each country, where the output is the name of the country and the city. I know this could be done with Max(), but I'm having a struggle limiting my table to showing all the countries name and showing onle the name of the most populated city.
SELECT country.name, city.name, MAX(city.Population)
FROM city
LEFT JOIN country
ON city.CountryCode=Country.Code
GROUP BY city.name, country.name, city.population
ORDER BY city.population DESC;
This only gives me all the countries and all the cities. Could anyone help me narrow it down so it only shows every countries name but with their largest city?

You want to first the max population in each country and then join it with the city table to know which city it belongs to. After that, join it with the country table to get the required result.
select co.name,
ct.name,
ct.population
from (
select c1.*
from city c1
join (
select countryCode,
max(population) population
from city
group by countryCode
) c2 on c1.countryCode = c2.countryCode
and c1.population = c2.population
) ct
join country co on ct.countryCode = co.code;
Another way of finding max in group using left join:
select co.name,
ct.name,
ct.population
from (
select c1.*
from city c1
left join city c2 on c1.countryCode = c2.countryCode
and c1.population < c2.population
where c2.countryCode is null
) ct
join country co on ct.countryCode = co.code;

Related

Count the repeats of foreign key of two tables

I have two tables Countries( id, country) and Cities (id, city, countryId ) I want to select countries and to show how much cities AS locations .
I tried this :
SELECT countryid, COUNT(*) AS locations
FROM Cities
GROUP BY countryid
but it shows me countryid instead of country
You need to join the tables as follows:
select c.country, count(*) as locations
from Country c
inner join Cities ci
on c.id = ci.countryId
group by c.id, c.country
I also included the country in the group by since it appears in the select clause

How do I count something the number of employee that is in a different table in SQL?

The question asks
"Write a query to display the city and country where an office is located and a count of the number of employees at that location. Order the results in descending order of the number of employees."
So far I have put,
SELECT city, country, SELECT COUNT(city,country)
FROM Offices
ORDER BY(SELECT COUNT(city,country)
FROM Offices)DESC;
It wont let me run it however. I reckon I made a mistake in the SELECT COUNT part.
The employees table contains
employeeNumber
lastName
firstName
extension
email
reportsTo
jobTitle
officeCode
The Office table contains
officeCode
city
phone
addressLine1
addressLine2
state
country
postalCode
territory
officeLocation
Anyone know what I'm doing incorrectly? Thank you! Sorry if this is a lot of stuff.
You can do it using a LEFT JOIN, GROUP BY and ORDER BY.
We need LEFT JOIN and GROUP BY to get the employee count and the ORDER BY to order the results in descending order of no of employees.
SELECT OfficeCode, City, Country, COUNT(E.employeeNumber) AS EmployeeCount
FROM Offices O
LEFT JOIN Employees E ON E.OfficeCode = E.OfficeCode
GROUP BY OfficeCode, City, Country
ORDER BY COUNT(E.employeeNumber) DESC
use join and count
SELECT city, country,officeLocation, COUNT(e.employeeNumber)
FROM Offices ofc join employees e on ofc.officeCode=e.officeCode
group by city, country,officeLocation
A couple ways to tackle this. Using a LEFT OUTER JOIN: (make sure to use a LEFT OUTER and not an INNER JOIN here or else you will only get locations with employees. That may work in your case but what if a location has no current employees?)
SELECT City, Country, COUNT(e.employeeNumber) AS EmployeeCount
FROM Offices o
LEFT OUTER JOIN Employees e
ON e.OfficeCode = o.OfficeCode
GROUP BY City, Country
ORDER BY 3 DESC
Or you could use a subquery with the select statement:
SELECT City, Country,
(SELECT COUNT(*) FROM Employees e WHERE o.OfficeCode = e.OfficeCode) AS EmployeeCount
FROM Offices o
ORDER BY 3 DESC

Using Oracle in select query

Question: Given the CITY and COUNTRY tables, query the sum of the populations of all cities where the CONTINENT is 'Asia'.
City table contains fields: CountryCode, Population
Country table contains fields: Code, Continent
(CITY.CountryCode and COUNTRY.Code are matching key columns.)
I tried the following query: (I know this can be solved using Inner join)
Select sum(city.population) from city
where city.countrycode in (Select code from Country where continent = 'Asia')
Hacker rank gives following error:
ERROR at line 3:
ORA-00933: SQL command not properly ended
Do you need a semi colon?
Something along these lines......
Per city..........
SELECT City.Name, SUM(City.Population)
FROM City INNER JOIN Country ON Country.Code = City.CountryCode
WHERE
Country.Continent = 'ASIA'
GROUP BY
City.Name;
Per Country & City
SELECT Country.Name, City.Name, SUM(City.Population)
FROM City INNER JOIN Country ON Country.Code = City.CountryCode
WHERE
Country.Continent = 'ASIA'
GROUP BY
Country.Name, City.Name;
Just the Total for ASIA
SELECT SUM(City.Population)
FROM City INNER JOIN Country ON Country.Code = City.CountryCode
WHERE
Country.Continent = 'ASIA';
What we are doing here is querying the city table and finding all matches in the country table by using the identifying field in both those tables:
country.code in your country table
city.countrycode in your city table
Whenever country.code = city.countrycode and country.continent= 'Asia', you will be returned the sum of that population.
Select sum(city.population) from city inner join country on country.code = city.countrycode
where country.continent= 'Asia';
I also recommend you select the city the population count belongs to:
Select city.name, sum(city.population) from city inner join country on country.code = city.countrycode
where country.continent= 'Asia';
This is the right code
Select sum(city.population)
from city inner join country on country.code = city.countrycode
where country.continent= 'Asia';
Select SUM(City.POPULATION) from City join Country ON city.countrycode=country.code
where country.continent='Asia'
Use ; at the end of the code.
Select sum(city.population) from city
where city.countrycode in (Select code from Country where continent = 'Asia');

For each country, find city that has the highest population and the city's population

I am using the Mondial database schema and am trying to find: For each country, find city that has the highest population and the city's population.
Right now I have:
SELECT Country.Name, city.name, MAX(city.population) Population
FROM city
Join Country
On Country.Code=City.Country
WHERE city.population IS NOT NULL
GROUP BY Country.Name, city.name
ORDER BY Country.Name;
This gives me ALL of the cities in each country and their populations and not just the largest city.
Use analytical functions. Something like this should work (untested):
select
country.name,
city.name,
city.population
from
country
join
(
select
country,
name,
population,
row_number() over ( partition by population desc) as rn
from
city
) city on
city.country = country.code
and city.rn = 1
order by
country.name
Don't know in oracle but if done in SQL Server it can be done like this:
Select * from
(select
Country.Name,
city.name,
city.population,
ROW_NUMBER() over(partition by Country.Name order by Country.Name,city.population desc) RowNum
from Country inner join city city on Country.Code=City.Country) tbl
where RowNum = 1
function similar to row_number in oracle will help.
Hope This help.
This seems to work.
It's also useful for filtering query results according to column containing an aggregate function.
SELECT ct.name AS "Country", c1.name AS "City", c1.population AS "Population"
FROM city c1
JOIN country ct
ON c1.country = ct.code
WHERE c1.population = (SELECT max(population)
FROM city c2
WHERE c1.country = c2.country)
ORDER BY country
Here you have already done Group by Country.name so you can just have single country detail, so instead of going for the MAX(population) you can just do order by city.population also remove the group by for city.name
E.g.
SELECT Country.Name, city.name, city.population Population
FROM city
Join Country
On Country.Code=City.countrycode
WHERE city.population IS NOT NULL
GROUP BY Country.Name
ORDER BY city.population desc;
This will not give you the countries in sorted order but that can also be done after adding another order by on top of it if you really want country name also sorted.
SELECT Country.Name, city.name, city.population Population
FROM city
Join Country
On Country.Code=City.countrycode
WHERE city.population IS NOT NULL
GROUP BY Country.Name
ORDER BY country.name, city.population desc;
Hope that helps to simplify the SQL query. This I have tested in MySQL.
You cannot use MAX in multiple select
try this:
SELECT Country.Name, city.name, city.population
FROM city
Join Country
On Country.Code=City.Country
WHERE city.population IS NOT NULL and city.population in (SELECT MAX(population) FROM city limit 1)
GROUP BY Country.Name, city.name
ORDER BY Country.Name;

SQL query - IS NULL

Tables:
Country
-------
PK CountryID
Name
City
-------
PK CityID
FK CountryID
Name
Airport
--------
PK AirportID
FK CityID
Name
My task is to select names of countries that have no airport.
I can imagine only one solution with EXCEPT (or MINUS)
SELECT Country.Name
FROM Country EXCEPT (SELECT DISTINCT Country.Name FROM Country, City, Airport
WHERE City.CountryID = Country.CountryID AND Airport.CityID = City.CityID);
But is it possible not to use EXCEPT but something like IS NULL?
SELECT cn.CountryID
FROM Country cn
LEFT JOIN City ct ON cn.CountryID = ct.CountryID
LEFT JOIN Airport ar on ar.CityID=ct.CityID
WHERE ar.AirportID is null
If you need to make this query with IS NULL try following query:
SQLFiddle demo
select ct.CountryId,max(ct.Name) from Country ct
left join City c on ct.CountryId=c.CountryId
left join Airport a on a.CityId=c.CityID
group by ct.CountryId
HAVING max(a.AirportID) IS NULL
You can use this, but it's basically the same thing you have with different syntax.
SELECT Country.Name
FROM Country
Where Country.Name Not IN
(
SELECT DISTINCT Country.Name FROM Country, City, Airport
WHERE City.CountryID = Country.CountryID AND Airport.CityID = City.CityID
);