I like to know how many users are from what city and Boroughs/Neighborhoods within that City. So I am looking for a query that will output the count results of these two. I have a table with user data, without the specific City and Boroughs/Neighborhoods, but with a postal code from each user. This can be used to match on the table postcodes, witch contains the City and Neighborhoods data.
Table Users
+----+--------------------+--------------+
| ID | User | Postcode |
+----+--------------------+--------------+
| 10 | John Doe | 1100—99-AB |
| 11 | Shara Lee | 1201—34-CD |
| 12 | Patrick Star | 1100—99-AB |
| 13 | Oswald Harvey | 1100—99-AB |
| 14 | Samuel Jackson | 1401—34-TR |
| 15 | Richard Lionheart | 1744—39-AA |
| 16 | Shamanta Jones | 2334—95-AC |
| 17 | James Rooney | 1401—34-TR |
| 18 | Chandler Bing | 3334—23-AA |
| 19 | Jessica Burner | 2277—99-RA |
+----+--------------------+--------------+
Table Postcodes
+------------+--------------+-------------+
| Postcode | City | Borough |
+------------+--------------+-------------+
| 1100—99-AB | New York | Manhattan |
| 1201—34-CD | New York | Manhattan |
| 1401—34-TR | New York | Bronx |
| 1744—39-AA | New York | Harlem |
| 2334—95-AC | Newark | |
| 6334—95-AC | Detroit | Greektown |
| 3334—23-AA | Philadelphia | Penn Center |
| 2277—99-RA | Newark | |
+------------+--------------+-------------+
Result I am after
+--------------+--------------+-------------+---------------+
| City | Total_City | Borough | Total_Borough |
+--------------+--------------+-------------+---------------+
| New York | 7 | Manhattan | 4 |
| New York | 7 | Bronx | 2 |
| New York | 7 | Harlem | 1 |
| Newark | 2 | | 2 |
| Philadelphia | 1 | Penn Center | 1 |
+--------------+--------------+-------------+---------------+
This is how far I got with my query. This does correctly count the number Boroughs/Neighborhoods, but unfortunately it does not show the total city count.
SELECT City, Borough, COUNT(City) AS Total_City, COUNT(Borough) AS Total_Borough,
FROM `users` u
LEFT JOIN `postcodes` p ON p.postcode = u.postcode
GROUP BY City, Borough
See my example on http://rextester.com/DFRV4183
Here's one way...
SELECT a.*, b.total total_city
FROM
( SELECT p.city
, p.borough
, COUNT(*) total
FROM postcodes p
JOIN myusers u
ON u.postcode = p.postcode
GROUP
BY city
, borough
) a
JOIN
( SELECT p.city
, COUNT(*) total
FROM postcodes p
JOIN myusers u
ON u.postcode = p.postcode
GROUP
BY city
) b
ON b.city = a.city;
You can also do something like this, but I'm not convinced that the result is easier to understand...
SELECT city
, borough
, COUNT(*) total
FROM postcodes p
JOIN myusers u
ON u.postcode = p.postcode
GROUP
BY city
, borough WITH ROLLUP;
Finally, you can use variables. Maybe I'll post an answer along those lines later... if someone doesn't beat me to it.
SELECT b.City, Borough, Total_City, Total_Borough from
(SELECT City, coalesce(COUNT(User),0) AS Total_City
FROM `Users` u
right JOIN `Postcodes` p ON p.postcode = u.postcode
GROUP BY City ) as c
inner join
(
SELECT City, coalesce(Borough,'Undefined')as Borough,coalesce( COUNT(User),0) AS Total_Borough, p.postcode
FROM `users` u
right JOIN `postcodes` p ON p.postcode = u.postcode
GROUP BY City, Borough
) as b
on b.City=c.City
Related
These are the tables I am fetching count from
register
+----+-------------+--------+
| id | empSignupId | cityId |
+----+-------------+--------+
| 42 | 4 | 1 |
| 47 | 3 | 1 |
| 48 | 11 | 1 |
| 54 | 20 | 1 |
| 55 | 21 | 2 |
| 56 | 22 | 2 |
+----+-------------+--------+
guest_list
+-----+------------+-------------+
| id | guestName | empSignupId |
+-----+------------+-------------+
| 103 | Mallica SS | 3 |
| 104 | Kavya | 3 |
| 108 | Vinay BR | 11 |
| 109 | Akash MS | 11 |
+-----+------------+-------------+
cities
+----+---------------+
| id | cityName |
+----+---------------+
| 1 | Bengaluru |
| 2 | Chennai |
| 3 | Sydney |
| 4 | New York City |
| 5 | Shanghai |
| 6 | Chicago |
+----+---------------+
I need to fetch the count of people registered from particular city which includes people, their guests, if guests are not present also it should show the count of people.
This is what I tried
SELECT COUNT(gl.id) + COUNT(rfs.id), ct.cityName, rfs.cityId
FROM register rfs
INNER JOIN cities ct ON ct.id=rfs.cityId
INNER JOIN guest_list gl ON gl.empSignupId = rfs.empSignupId
GROUP BY rfs.cityId;
+-------------------------------+-----------+--------+
| COUNT(gl.id) + COUNT(rfs.id) | cityName | cityId |
+-------------------------------+-----------+--------+
| 8 | Bengaluru | 1 |
+-------------------------------+-----------+--------+
I also need the count of people from other cities to be displayed, since there are no guests from some cities its not returning that count.
Please help me figure this out, I am still new to MySQL.. any help is greatly appreciated.
You fist need to aggregate guest_list table in order to get the number of records per empSignupId:
SELECT empSignupId, COUNT(empSignupId) AS countGuest
FROM guest_list gl
GROUP BY empSignupId
Output:
empSignupId countGuest
----------------------
3 2
11 2
Now you have to use a LEFT JOIN to the derived table above in order to also get the number of records for each city:
SELECT COALESCE(SUM(countGuest), 0) + COUNT(rfs.id), ct.cityName, rfs.cityId
FROM register rfs
INNER JOIN cities ct ON ct.id=rfs.cityId
LEFT JOIN (
SELECT empSignupId, COUNT(empSignupId) AS countGuest
FROM guest_list gl
GROUP BY empSignupId
) gl ON gl.empSignupId = rfs.empSignupId
GROUP BY rfs.cityId;
Output:
COALESCE(SUM(countGuest), 0) + COUNT(rfs.id) cityName cityId
------------------------------------------------------------------
8 Bengaluru 1
2 Chennai 2
Using LEFT JOIN instead of INNER JOIN guarantees that we also get cities without guests.
Demo here
Note: If you also want to get cities without registrations then you need to place the cities table first and use a LEFT JOIN to register.
Use LEFT JOINS and add count(distinct r.empSignupId) + count(distinct g.id):
select
c.id as cityId,
c.cityName,
count(distinct r.empSignupId) + count(distinct g.id) as people_count
from cities c
left join register r on r.cityId = c.id
left join guest_list g on g.empSignupId = r.empSignupId
group by c.id;
The result would be:
| cityId | cityName | people_count |
|--------|---------------|--------------|
| 1 | Bengaluru | 8 |
| 2 | Chennai | 2 |
| 3 | Sydney | 0 |
| 4 | New York City | 0 |
| 5 | Shanghai | 0 |
| 6 | Chicago | 0 |
Demo: http://rextester.com/OTBH14189
If you don't need the rows with 0, change the first LEFT JOIN to an inner JOIN.
I have three tables with the following data:
countries
+-----+----------+
| id | name |
+-----+----------+
| 1 | country1 |
| 7 | country2 |
+-----+----------+
states
+-----+----------+------------+
| id | name | country_id |
+-----+----------+------------+
| 3 | state1 | 1 |
| 9 | state2 | 7 |
| 11 | state3 | 1 |
| 17 | state4 | 1 |
+-----+----------+------------+
cities
+-----+----------+------------+
| id | name | state_id |
+-----+----------+------------+
| 5 | city1 | 3 |
| 6 | city2 | 9 |
| 22 | city3 | 9 |
| 24 | city4 | 17 |
| 25 | city5 | 11 |
| 26 | city6 | 11 |
+-----+----------+------------+
I’m trying to select all data so that I can generate the following output:
+-----+---------------------------+--------+-------+
| id | table_name | country | state | city |
+-----+---------------------------+--------+-------+
| 1 | countries | country1 | | |
| 3 | states | country1 | state1 | |
| 5 | cities | country1 | state1 | city1 |
| 11 | states | country1 | state3 | |
| 25 | cities | country1 | state3 | city5 |
| 26 | cities | country1 | state3 | city6 |
| 17 | states | country1 | state4 | |
| 24 | cities | country1 | state4 | city4 |
| 7 | countries | country2 | | |
| 9 | states | country2 | state2 | |
| 5 | cities | country2 | state2 | city2 |
| 5 | cities | country2 | state2 | city3 |
+-----+---------------------------+--------+-------+
I know it’s challenging, but I was wondering if that is possible to generate such a result with a SELECT or can it only be done programmatically? Thanks!
You need these 3 SQL statements:
All Cities:
SELECT cit.id, 'cities', cont.name, st.name, cit.name
FROM countries cont
INNER JOIN states st ON cont.id = st.country_id
INNER JOIN join cities cit ON st.id = cit.state_id
All states:
SELECT stat.id, 'states', cont.name, st.name, ''
FROM countries cont
INNER JOIN states st ON cont.id = st.country_id
All countries;
SELECT cont.id, 'countries', cont.name, '', '' FROM countries cont
Then you can combine them all like
SELECT cit.id, 'cities', cont.name, st.name, cit.name
FROM countries cont
INNER JOIN states st ON cont.id = st.country_id
INNER JOIN join cities cit ON st.id = cit.state_id
UNION ALL
SELECT stat.id, 'states', cont.name, st.name, ''
FROM countries cont
INNER JOIN states st ON cont.id = st.country_id
UNION ALL
SELECT cont.id, 'countries', cont.name, '', '' FROM countries cont
You can use below query
SELECT C.id, C.name AS table_name, 'country1' AS country, S.name AS state, CI.city
FROM COUNTRIES C
FULL OUTER JOIN STATES S
ON (C.ID = S.ID)
FULL OUTER JOIN CITIES CI
ON (C.ID=CI.ID);
Or you can use
SELECT C.id, C.name AS table_name, 'country1' AS country, S.name AS state, CI.city
FROM COUNTRIES C, STATES S, CITIES CI
WHERE C.ID = (+)S.ID AND
C.ID=(+)CI.ID;
I'd written this before I saw #nos had already supplied a virtually identical answer. This version adds field aliases, sorts the data as per the OP's sample output and avoids a typo.
select
c.id,
'countries' as table_name,
c.name as country,
'' as state,
'' as city
from countries c
union
select
s.id,
'states' as table_name,
c.name as country,
s.name as state,
'' as city
from countries c
JOIN states s ON c.id = s.country_id
union
select
ci.id,
'cities' as table_name,
c.name as country,
s.name as state,
ci.name as city
from countries c
JOIN states s ON c.id = s.country_id
JOIN cities ci ON s.id = ci.state_id
order by country, state, city
mysql> select * from Orders;
+------+------+------+------------+------------+
| ONO | CNO | ENO | RECEIVED | SHIPPED |
+------+------+------+------------+------------+
| 1020 | 1111 | 1000 | 1994-12-10 | 1994-12-12 |
| 1021 | 1111 | 1000 | 1995-01-12 | 1995-01-15 |
| 1022 | 2222 | 1001 | 1995-02-13 | 1995-02-20 |
| 1023 | 3333 | 1000 | 2003-02-15 | NULL |
| 1024 | 4444 | 1000 | 2003-02-15 | 2003-02-16 |
| 1025 | 5555 | 1000 | 2003-02-15 | 2003-02-16 |
+------+------+------+------------+------------+
mysql> select * from Employees;
+------+--------+-------+------------+
| ENO | ENAME | ZIP | HDATE |
+------+--------+-------+------------+
| 1000 | Jones | 67226 | 1995-12-12 |
| 1001 | Smith | 60606 | 1992-01-01 |
| 1002 | Brown | 50302 | 1994-09-01 |
| 1003 | Green | 28411 | 2002-09-01 |
| 1004 | Purple | 28411 | 2003-01-01 |
+------+--------+-------+------------+
mysql> select * from Customers;
+------+---------+------------------+-------+--------------+
| CNO | CNAME | STREET | ZIP | PHONE |
+------+---------+------------------+-------+--------------+
| 1111 | Charles | 123 Main St. | 67226 | 316-636-5555 |
| 2222 | Bertram | 237 Ash Avenue | 67226 | 316-689-5555 |
| 3333 | Barbara | 111 Inwood St. | 60606 | 316-111-1234 |
| 4444 | Will | 111 Kenwood St. | 54444 | 416-111-1234 |
| 5555 | Bill | 211 Marlwood St. | 28408 | 416-111-1235 |
| 6666 | Keely | 211 Pinewood St. | 28411 | 416-111-1235 |
| 7777 | Maera | 211 Marlwood St. | 28408 | 416-111-1235 |
+------+---------+------------------+-------+--------------+
I need to: Get cname and ename pairs such that the customer with name
cname has placed an order through employee with name ename.
I'm sure this seems easy to most but I have not been able to figure
this out. I have tried this:
select distinct Customers.CNAME, Employees.ENAME
from Customers, Employees
where Customers.CNO in (
select Customers.CNO
from Customers, Orders
where Customers.CNO = Orders.CNO
) and
where Employees.ENO in (
select Employees.ENO
from Orders, Employees
where Employees.ENO = Orders.ENO
);
in multiple versions, but I can't seem to get it to work. This is my first time working in SQL so it is very new to me. I would really appreciate any help.
select customers.CNAME, employees.ENAME from customers
inner join orders on customers.CNO = orders.CNO
inner join employees on orders.ENO = employees.ENO;
Using join statements makes it easier to read the SQL you are trying to do. This joins orders table to customers on the CNO value and orders table with employees on the ENO value. It then selects two columns for display.
try this
SELECT DISTINCT Customers.CNAME,Employees.ENAME FROM Customers
JOIN Orders ON Customers.CNO=Orders.CNO
JOIN Employees ON Employees.ENO=Orders.ENO;
or
SELECT DISTINCT Customers.CNAME,Employees.ENAME from Customers
JOIN Orders USING (CNO)
JOIN Employees USING(ENO);
You could use a select distinc with a pair of join ( left join if could be that the on condition don't match or inner join if ever match )
select distinct c.cname, e.ename
from Customers as c
left join Orders as o as o on o.cno = c.cno
left join Employees on e.eno = o.eno
select distinct c.cname, e.ename
from Customers as c
inner join Orders as o as o on o.cno = c.cno
inner join Employees on e.eno = o.eno
SELECT DISTINCT c.cname, e.ename
FROM orders o
JOIN employees e USING (eno)
JOIN clients c USING (cno);
Task: From MySQL standard database "world" select all the cities with population more then a million, limiting number of countries to 10.
If I do this:
SELECT country.Name, city.Name, city.Population
FROM country
INNER JOIN city
ON country.Code = city.CountryCode
WHERE city.Population >= 1000000
LIMIT 10;
it produces this:
+-------------+--------------+------------+
| Name | Name | Population |
+-------------+--------------+------------+
| Afghanistan | Kabul | 1780000 |
| Algeria | Alger | 2168000 |
| Angola | Luanda | 2022000 |
| Argentina | Buenos Aires | 2982146 |
| Argentina | La Matanza | 1266461 |
| Argentina | Córdoba | 1157507 |
| Armenia | Yerevan | 1248700 |
| Australia | Sydney | 3276207 |
| Australia | Melbourne | 2865329 |
| Australia | Brisbane | 1291117 |
+-------------+--------------+------------+
Argentina, for example, is repeated 3 times. I need to limit number of countries to 10, not number of rows.
GROUP BY won't do since I need all the cities, I don't need them grouped.
The expected result would be this:
+--------------------+----------------------------+------------+
| Name | Name | Population |
+--------------------+----------------------------+------------+
| Afghanistan | Kabul | 1780000 |
| Algeria | Alger | 2168000 |
| Angola | Luanda | 2022000 |
| Argentina | Buenos Aires | 2982146 |
| Argentina | La Matanza | 1266461 |
| Argentina | Córdoba | 1157507 |
| Armenia | Yerevan | 1248700 |
| Australia | Sydney | 3276207 |
| Australia | Melbourne | 2865329 |
| Australia | Brisbane | 1291117 |
| Australia | Perth | 1096829 |
| Azerbaijan | Baku | 1787800 |
| Bangladesh | Dhaka | 3612850 |
| Bangladesh | Chittagong | 1392860 |
| Brazil | São Paulo | 9968485 |
| Brazil | Rio de Janeiro | 5598953 |
| Brazil | Salvador | 2302832 |
| Brazil | Belo Horizonte | 2139125 |
| Brazil | Fortaleza | 2097757 |
| Brazil | BrasÃlia | 1969868 |
| Brazil | Curitiba | 1584232 |
| Brazil | Recife | 1378087 |
| Brazil | Porto Alegre | 1314032 |
| Brazil | Manaus | 1255049 |
| Brazil | Belém | 1186926 |
| Brazil | Guarulhos | 1095874 |
| Brazil | Goiânia | 1056330 |
| United Kingdom | London | 7285000 |
| United Kingdom | Birmingham | 1013000 |
+--------------------+----------------------------+------------+
As you can see, number of countries is 10, no matter how many cities.
Of course, my database is different. I used the "world" for simplicity, generality, and availability.
In the real db I also do some filtering on "country".
I Hope this will work
SELECT country.Name, city.Name, city.Population
FROM country
LEFT JOIN city
ON country.Code = city.CountryCode
WHERE city.Population >= 1000000
AND city.id IN (SELECT id FROM city WHERE city.Population >= 1000000 AND country.Code = city.CountryCode LIMIT 10);
//So sorry try this query
SELECT country.Name, city.Name, city.Population
FROM country
LEFT JOIN city
ON country.Code = city.CountryCode
WHERE city.Population >= 1000000 and country.Code IN(SELECT distinct CountryCode FROM city WHERE Population >= 1000000 LIMIT 10);
Generate temporary row level id's for each of the unique country in a sub query and select rows from it applying a where condition like where temp_row_num is <= 10.
Example:
select
/*uq_country_row_num, */
country_name, city_name, population
from (
select country_name, city_name, population
, case when #pn=(#cn:=country_name)
then #r:=(#r + 1)
else #r:=1
end as uq_country_row_num
, #pn:=#cn as temp_cn
from population,
(select #pn:='', #cn:='', #r:=0) country_rown_nums
-- use order by country_name if the result set is un-ordered
order by
country_name
) all_results
where
uq_country_row_num <= 10
;
You can un comment the variable /*uq_country_row_num, */, if you want them as part of the output.
Example # SQL Fiddle
Edit:
From the comments:
You mean 10 rows per country or all records from max 10 countries?
Exactly, "all records from max 10 countries".
select
country_id,
country_name, city_name, population
from (
select
country_name, city_name, population
, case when #pn=(#cn:=country_name)
then #country_id:=#country_id
else #country_id:=(#country_id + 1)
end as country_id
, #pn:=#cn as temp_cn
from population,
(select #pn:='', #cn:='', #row_num:=0, #country_id:=0) country_row_nums
order by country_name
) all_results
where
country_id <= 10
;
Example 2 # SQL Fiddle
Try this once
SELECT city.Name, city.Population, newcountry.name
FROM city
INNER JOIN
(select distinct Name,Code
from country limit 10) newcountry
ON newcountry.Code = city.CountryCode
WHERE city.Population >= 1000000;
None of the answers worked. So I had to use the following request:
SELECT co.Code, co.Name, ci.Name, ci.Population
FROM city ci
INNER JOIN (
SELECT DISTINCT co.Code, co.Name
FROM country co
INNER JOIN city ci
ON ci.countryCode = co.Code
WHERE ci.Population > 1000000
ORDER BY co.Name
LIMIT 10
) co
ON ci.countryCode = co.Code
WHERE ci.Population > 1000000;
It seems rather clumsy and not efficient to me (notice the repetition of the condition), but for lack of a better way, this is the only solution.
Thanks to everyone for your answers anyway.
Lets say I have the following tables:
Countries
---------------------------
| ID | Country Name |
---------------------------
| 1 | Greece |
| 2 | Italy |
| 3 | Spain |
---------------------------
Cities
---------------------------
| ID | City |
---------------------------
| 1 | Athens |
| 2 | Patra |
| 3 | Rome |
| 4 | Venice |
---------------------------
Countries & Cities
--------------------
| ID | Cntr | City |
--------------------
| 1 | 1 | 2 |
| 2 | 1 | 1 |
| 3 | 2 | 3 |
--------------------
Now, How can I run a MySQL query that will return the name of the countries and the total cities based on table "Countries & Cities" ?
In example to return:
---------------------------
| Cities | Country |
---------------------------
| 2 | Greece |
| 1 | Italy |
---------------------------
Try this out:
SELECT COUNT(cs.City) as Cities, cn.name as Country
FROM countries cn
INNER JOIN country_city cs ON cs.Cntr = cn.id
GROUP BY cn.name
OUTPUT:
2 | Greece
1 | Italy
There is only one JOIN is needed
SELECT `c`.`name`, COUNT(`c`.id)
FROM `countries_cities` AS `cc`
JOIN `countries` AS `c`
ON `c`.id = `cc`.country_id
GROUP BY `cc`.country_id
SELECT cn.Name, COUNT(*)
FROM CountriesAndCities cc
JOIN Countries cn ON (cn.ID = cc.Cntr)
GROUP BY cn.Name
You only need to group the countries in the countries & cities table:
SELECT COUNT(1), c.Name
FROM [countriesAndCities] cnc
INNER JOIN [country] c ON cnc.cnt = c.id
GROUP BY c.Name