I have recently attended an interview on SQL. Below is the question:
Write a query to retrieve city name, state name, city population and return the following calculations along with the before mentioned fields.
Average city population in the state.
Difference between the city population and average city population in that state.
City Table:
City_Name
State_NAme
Population
Baltimore
Maryland
30000
College Park
Maryland
18000
Columbia
Maryland
20000
Boston
Massachusetts
35000
Malden
Massachusetts
10000
Dover
Delaware
20000
Jersey City
New Jersey
35000
I have tried below query but I didnot get desired output. Can anyone help me with correct query?
select * from city_table;
select state_name, sum(population)/count(city_name) as average_city_pop
from city_table
group by state_name;
You need to explore sql more, learn about aggregation functions and joins. Your query is correct in obtaining the average population. You need to join it to the original table to get your result.
with avg_city_pop as (select state_name, avg(population) as avg from city group by state_name)
select c.*, acp.avg as average_city_population, abs(acp.avg-c.population) as difference from city c inner join avg_city_pop acp on c.state_name = acp.state_name;
try it out here
For MySQL versions before 8.0, we can use a correlated subquery to get the average population for each state, which can alss be used to calculate the gap between city population and state average population. Note, the abs function is optionally used to always return a positive number. Omit it if necessary.
select city_name,state_name,(select avg(population) from city where state_name=c.state_name group by state_name ) as average_pop ,
abs(population - (select avg(population) from city where state_name=c.state_name group by state_name )) as gap_pop
from city c;
select
city_name,
state_name,
population,
avg(population) over (partition by state_name) as Avg_pop,
population-avg(population) over (partition by state_name) as Difference
from city;
see sqlfilldle: https://www.db-fiddle.com/f/tVxdH6bQvsu48umWgLmrQB/0
This needs MySQL 8.0+, because over_clause is available since 8.0.
output:
city_name
state_name
population
Avg_pop
Difference
dover
delaware
20000
20000.0000
0.0000
baltimore
maryland
30000
22666.6667
7333.3333
college park
maryland
18000
22666.6667
-4666.6667
columbia
maryland
20000
22666.6667
-2666.6667
boston
massachussets
35000
22500.0000
12500.0000
molden
massachussets
10000
22500.0000
-12500.0000
jersey city
new jersey
35000
35000.0000
0.0000
Related
I have a table like this:
LocationID CountryName CustomerAmount
C01 Australia 500
C02 Australia 200
C03 China 100
C04 China 200
C05 Japan 50
C06 Canada 120
I want to find the "number of customers in each country" AND the total number of customers.
Now I have the following query:
select countryName, sum(CustomerAmount)
from test
group by countryName;
I obviously got this output:
CountryName. customerAmount
Australia 700
China 300
Japan 50
Canada 120
But I want the output like this
CountryName. customerAmount totalAmount
Australia 700 1170
China 300 1170
Japan 50 1170
Canada 120 1170
My problem is how can I put two same sum(customerAmount) side by side, but one is grouped by countryName, while the other just sum up all values in customerAmount table.
Thank you in advance!!!! I have to say sorry as my expression may be ambiguous.
One easy way is just to use a sub-query like
select countryName, sum(CustomerAmount) customerAmount,
(select Sum(customerAmount) from test) totalAmount
from test
group by countryName;
If you can use window functions (MySql 8+) you can do
select countryName, sum(CustomerAmount) customerAmount,
sum(Sum(CustomerAmount)) over() totalAmount
from test
group by countryName;
note the nested sum().
SELECT countryName, SUM(CustomerAmount), SUM(CustomerAmount) OVER()
FROM test
GROUP BY countryName;
I did not test this, but using the over clause should do what you are looking for as seen here.
I have a table like this
id name city
-------------------------------
1 Ian London
2 John London
3 David New York
4 Sylvia Mumbai
5 Beryl New York
6 Rashan London
I would like to retrieve the data with a row numbering that is grouped on City. Like this.
name city count
-------------------------------
Ian London 0
John London 1
Rashan London 2
Beryl New York 0
David New York 1
Sylvia Mumbai 0
I have been trying with
ROW_NUMBER() OVER (PARTITION BY City ORDER BY name)-1
But the count is of all the items returned, where I would like to count the number of people in each city.
Your code should do what you want - however, you mention group by, which is irrelevant here. The query should just be:
select name, city, row_number() over(partition by city order by name) - 1 rn
from mytable
To get the results that you specify:
select name, city, row_number() over (partition by city, order by name) as count
from t
order by count(*) over (partition by city) desc, -- number of rows in city
city,
name;
You seem to want the cities ordered by the number of names in the city.
The table name is c_list.
Country City Rating Date
------------------------------------
France Brest 95 24092016
France Brest 98 27092016
France Brest 95 03102016
France Lille 100 26092016
France Lille 92 28092016
Japan Tokyo 98 02102016
There are more than 50 different countries and each country have few cities. And each city may have more than one row of record or more. I want to select one City with highest average Rating (Compare to Cities in it's own country) and then compare with all other cities in different countries. So, the final query should display all Country and their ONE City with max(avg(Rating)) and in desc order. The sample output:
Country City max(avg(rating))
-------------------------------------
USA New York 97.25
UK Cardiff 96.70
Germany Greven 96.50
Turkey Afyon 94.88
France Guipavas 94.10
Canada Cartwright 91.35
I can only get the max(avg(rating)) for one country. Need help.
SELECT top 1 country, city, Avg(rating) AS Ratings
FROM c_list
where country = 'France'
GROUP BY city, country
order by Ratings desc
(Edited) The result that I want is similar like Miss world contest. Compete and win against local contestant in your country first. Next (my final result set) is to compete against the winners from other countries and rank them first to last using their avg(rating) that they got eatlier in their country.
If am not wrong you are looking for this
SELECT country,
city,
Avg(rating) AS Ratings
FROM c_list A
GROUP BY city,
country
HAVING Avg(rating) = (SELECT TOP 1 Avg(rating) AS Ratings
FROM c_list B
WHERE a.country = b.country
GROUP BY city
ORDER BY ratings DESC)
ORDER BY ratings DESC
Note : If you are using Mysql the replace TOP keyword with LIMIT
Base table:
select t.* from temp_lax t
COUNTRY CITY RATING
1 France Brest 95
2 France Brest 98
3 France Brest 95
4 France Lille 100
5 France Lille 92
6 Japan Tokyo 98
Query:
select t1.country, t1.city, Avg(t1.Rating) rating
from temp_lax t1
group by t1.country, t1.city
having avg(t1.rating) = (select max(avg(rating))
from temp_lax t2
WHERE t1.country = t2.country
GROUP BY t2.city)
order by rating desc
OUTPUT:
COUNTRY CITY RATING
1 Japan Tokyo 98
2 France Lille 96
3 France Brest 96
Please let me know if you are looking for different result set.
SQL Query:
Aim:
Write a SQL query to retrieve the address of highest rated Phills
Coffee in United States addressing format.
id name house street city state zip country rating
1 Best Buy 34 Main St Carson CA 98064 USA 9
2 Phills Coffee 4568 Sepulveda Blvd Torrance CA 50833 USA 6
3 Starbucks 3 Ocean Blvd Long Beach WA 45093 USA 9
4 Phills Coffee 214 Carson St Huntington Beach PA 89435 USA 4
US Addressing Format (For people outside USA):
http://bitboost.com/ref/international-address-formats/united_states/
My attempt:
SELECT house, street, city,
state,country,zip
FROM table
WHERE name="Phills Coffee"
ORDER BY rating DESC LIMIT 1
Am I doing wrong? Or How can I improve this query?
Thanks,
US address format would be like:
4568 Sepulveda Blvd, Torrance, CA 50833 USA.
So your select would look like:
SELECT CONCAT(house, ' ', street, ', ', city, ', ', state, ' ', zip, ' ', country)
FROM table
WHERE name="Phills Coffee"
ORDER BY rating DESC LIMIT 1
You've been asked to retrieve the address, and in United States addressing format. So use that :
SELECT CONCAT(street,' ','country', ',') ...
Dont know what is the US addressing format, but use concat to get it done. Your WHERE condition and ORDER BY are OK
You will have to use Max(rating) As Highest Rating and Group By for this,
SELECT house, street, city,
state,country,zip,Max(rating)
FROM table
Group By house, street, city,
state,country,zip
Having name="Phills Coffee"
ORDER BY rating DESC LIMIT 1;
I hope it works out for you, I am sorry if I wasn't any help..
SELECT house, street, city, state, country, zip, rating
FROM table WHERE rating = (SELECT MAX(rating)
from table WHERE name = "Phills Coffee")
AND name= "Phills Coffee";
This should return:
4568 Sepulveda Blvd Torrance CA 50833 USA 6
Note that you can omit rating from the first line of this query and it will return the address only (no 6, but will still select the max rating's info)
I have two tables on MySQL (using phpMyAdmin), looking like the following:
Table 1:
Country Total Minutes
USA 100
USA 90
Canada 60
Mexico 80
UK 90
France 70
France 10
Germany 10
In Table 2, what I need to do is the following:
Region Total Minutes
North America USA+USA+Canada+Mexico Mins
Europe UK+France+France+Germany Mins
Is there a way to have a row be the result of a query?
You either need a region column in table 1:
SELECT region, SUM(`Total Minutes`)
FROM timespent
GROUP BY region;
Or a separate region <-> country table:
SELECT region, SUM(`Total Minutes`)
FROM myregions r
INNER JOIN timespent t USING (country)
GROUP BY r.region;
The regions table would look like this:
region | country
--------------+--------
North America | USA
North America | Mexico
If you can't change anything in your database, look at Andomar's solution :)
You could translate the countries to regions in a subquery. The outer query can then group by on region:
select Region
, sum(TotalMinutes) as TotalMinutes
from (
select case country
when 'USA' then 'North America'
when 'France' then 'Europe'
end as Region
, TotalMinutes
from YourTable
) as SubQueryAlias
group by
Region