I have a set of tables in a SQL database :
states={id, name} :
id
name.
1
PACA
2
Ile de France
counties={id, name, state_id},
id
name
state_id
1
Paris.
2
2
Bouches du Rhône
1
3
Var
1
cities={id, name, population, county_id}
id
name
population
county_id
1
Paris
2000000
1
2
Marseille
1900000
2
3
Toulon
952000
2
4
Hyères
52575
2
And would be able to extract the most populate city by counties, i.e :
city_name
most_populated
county_name
Paris.
2000000.
Paris.
Marseille
1900000.
Bouches.
Try to execute this query, without success :
SELECT c.id cid, c.name, ci.name,
(SELECT sci.population FROM counties sc JOIN cities sci
ON sc.id = sci.county_id
WHERE sc.id = cid
ORDER BY sci.population DESC
LIMIT 1) AS city_most_populated
FROM counties c JOIN cities ci ON c.id = ci.county_id
GROUP BY c.id;
The result is not what i expected, and don't know how to acheive this kind of query.
Thx for help
Fro MySQL 5.x (which doesn't have ROW_NUMBER()), you can move your correlated sub-query in to the JOIN.
Find the most populated city in the correlated sub-query
Join on only that one city
Note: There is ambiguity as to what you want to happen if two cities are tied for the most populated city in a county. The query below picks the most populated city, per county, then if there are ties for most populated it picks One of those arbitrarily, based on the id.
SELECT
c.id cid,
c.name,
ci.name,
ci.population
FROM
counties c
JOIN
cities ci
ON ci.id = (
SELECT id
FROM cities
WHERE county_id = c.id -- This is what makes it "correlated", it's similar to joining the query to the counties table
ORDER BY population DESC, id DESC
LIMIT 1
)
In this query there are two references to the cities table. This enables the correlated sub-query to process all cities per county then return one id, allowing the join on to the other cities reference to be on to exactly one row. (Having two references to the same table also requires use of aliases.)
Demo: https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=73e93e61f88efee11e02f1e832c8510b
EDIT:
I had ON c.id = but that was a typo.
It is now corrected to ON ci.id =
If you're using MySQL 8+ then use ROW_NUMBER here:
WITH cte AS (
SELECT c.id AS city_name, c.population, cn.name AS county_name,
ROW_NUMBER() OVER (PARTITION BY cn.id ORDER BY c.population DESC) rn
FROM cities c
INNER JOIN counties cn ON cn.id = c.county_id
)
SELECT city_name, population, county_name
FROM cte
WHERE rn = 1;
You would use row_number():
SELECT cc.*
FROM (SELECT c.id as cid, c.name as country_name, ci.name as city_name,
ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY ci.population DESC) as seqnum
FROM counties c JOIN
cities ci
ON c.id = ci.county_id
) cc
WHERE seqnum = 1;
Related
Can you help me to find the proper MySQL query to get the most numbers of vendors per a given location and list them all by name and name of their shop:
1 - The query must find out which location has the highest number of vendors then list them by name with the name of the shop they work in.
I have the following tables:
CITIES
(
ID "unique",
NAME
)
SHOPS
(
ID "unique",
NAME,
CITY_ID ( foreign key of CITIES TABLE ID)
)
VENDORS
(
ID "unique",
NAME,
SHOP_ID ( foreign key of SHOPS TABLE ID)
)
Example with dummy data
CITIES : NY, SF
SHOPS: Boom - NY, Flash - NY, Sofast - SF
Vendors:
Mark : Boom,
John : Boom,
Carlos : Sofast,
Alex : Sofast,
David : Flash,
James: Flash
The NY has the highest number of vendors so it should list
Mark : Boom, John : Boom, David : Flash, James: Flash
Check if this works -
Select vendors.name, shops.name
from
cities inner join shops on cities.id= shops.city_id
inner join vendors on shops.id = vendors.shop_id
where cities.id = (select id from (select cities.id, count(1) from
cities inner join shops on cities.id= shops.city_id
inner join vendors on shops.id = vendors.shop_id
group by cities.id order by 2 desc) limit 1)
If you are running MySQL 8.0, you could approach this with window functions:
select *
from (
select x.*, rank() over(order by cnt) rn
from (
select v.*, count(*) over(partition by c.id) cnt
from cities c
inner join shops s on s.city_id = c.id
inner join vendors v on v.shop_id = s.id
) t
) t
where rn = 1
The most inner query joins the three tables, and counts how many vendors each city has. The next level ranks records by descending count. Finally, the last level filters on top-ranked rows.
Lets say I have this tables:
country:
country_id,
country_name;
currency:
currency_id,
currency_name;
country_currency:
country_id,
currency_id;
I would like to select and show all countries having two or more currencies. How should my query look like?
Join all the tables with the common columns, then group the result by country_id, and count the number of rows (or currency) per group as shown below.
SELECT A.COUNTRY_ID, COUNT(*) NUMBER_OF_CURRENCY
FROM COUNTRY A
INNER JOIN COUNTRY_CURRENCY B ON A.COUNTRY_ID = B.COUNTRY_ID
INNER JOIN CURRENCY C ON B.CURRENCY_ID=C.CURRENCY_ID
GROUP BY A.COUNTRY_ID
HAVING NUMBER_OF_CURRENCY > 1 ;
A better query would be:
SELECT COUNTRY_NAME
FROM COUNTRY
WHERE COUNTRY_ID IN (
SELECT COUNTRY_ID
FROM COUNTRY_CURRENCY
GROUP BY COUNTRY_ID
HAVING COUNT(*) > 1
);
tried to display the name of the department that has the least student count.
Try something like this:
SELECT TOP 1 department_name, count(*) AS number_of_students
FROM department natural join student
GROUP BY department_name
ORDER BY number_of_students
It will give you the list of departments ordered by the number of students. By selecting only the first row via TOP 1 you will only get the department with the least number of students.
Is it like this way?
SELECT
T1.department_name, COUNT(T2.department_id) totalCount
FROM department T1
LEFT JOIN student T2
ON T1.department_id = T2.department_id
GROUP BY T2.department_id
HAVING COUNT(T2.department_id) =
(
SELECT
COUNT(T2.department_id) totalCount
FROM department T1
LEFT JOIN student T2
ON T1.department_id = T2.department_id
GROUP BY T2.department_id
ORDER BY totalCount ASC
LIMIT 1
)
SQLFIDDLE DEMO
I have a couple tables in MySQL DB
EID Name
1 Title A
2 Title B
3 Title C
LID EID Location Address Order
1 1 Office NY 1
2 1 Home IL 2
3 2 Office CA 1
4 3 Home NJ 2
I have the above 2 tables (Employee and Location). I would like to know the location of each Employee with office as a preferred choice and if 'office' does not exist then would need 'Home' location . The order column defined the order/priority of what is needed.
here is the output needed
EID LID Name Location Address
1 1 Title A Office NY
2 3 Title B Office CA
3 4 Title C Home NJ
The first join of the query below just connects the Employee and Location tables, but note that it results in all records from Location being joined. The critical part of the below query is the second INNER JOIN to a subquery. This subquery identifies the minimum (i.e. highest priority) order for each employee ID. This is then used to discard records from the first join which are not the highest priority.
SELECT t1.EID,
t2.LID,
t1.Name,
t2.Location,
t2.Address
FROM Employee t1
INNER JOIN Location t2
ON t1.EID = t2.EID
INNER JOIN
(
SELECT EID, MIN(`Order`) AS min_order
FROM Location
GROUP BY EID
) t3
ON t2.EID = t3.EID AND
t2.Order = t3.min_order
One other note: Don't name your columns Order, which is a MySQL keyword. To get my query to work, I had to put it in backticks, which is inconvenient to say the least, and possibly error prone.
Demo here:
SQLFiddle
There are two posibility to get your result.
1)If you need Based on Order result then use this query
SELECT e1.EID, l1.LID, e1.Name, l1.Location, l1.Address
FROM Employee e1
JOIN
(SELECT MIN(`Order `) as Minorder, EID, LID, Location, Address, Order
FROM Location l1
GROUP BY EID) l1
ON l1.EID = e1.EID AND l1.Minorder = l1.Order;
2)if you need result Based on EID then use this query
SELECT e1.EID,l1.LID,e1.Name,l1.Location,l1.Address
FROM Employee e1 JOIN
(SELECT MIN(`EID`)as Mineid,EID,LID,Location,Address,`Order` FROM Location l1 GROUP BY EID)l1
ON l1.Mineid = e1.EID;
Extra Note:-
Plese donot use mysql inbuilt keyword as Column name or Table name for more information read this link click here
You can the expected result by using inner join
Select a.eid,b.Lid,a.name,b.location,b.address from Table1 a innner join (select * from Tableb group by eid) b on
a.eid=b.eid;
you can try this code this will help you as i think
select E.EID,E.name,ad.LID,ad.LOCATION,ad.ADDRESS,ad.[order]
from #emp E inner join #address ad on E.EID = ad.EID
inner join (select EID, min([order]) [order]
from #address
group by EID) tt on ad.EID = tt.EIDand ad.[order] = tt.[order]
I have these two tables:
CITY TABLE
CLUB TABLE
What I'm trying to do, is to select with the same query all cities that contain published clubs (published field set to 1) and the total of clubs published in that city.
At the moment, I am doing it with two steps, but I would like to improve performance by merging these in just one query.
SELECT c.id, c.name, c.slug
FROM city c, club cl
WHERE c.id = cl.city_id
AND ( SELECT COUNT(*)
FROM club cl, city c
WHERE cl.city_id = c.id AND cl.published = 1) > 0
GROUP BY c.id
After this, I'm doing a query for each city just to get the COUNT.
Something like this:-
SELECT city.id, city.name, city.slug, COUNT(club.id) AS club_count
FROM city
INNER JOIN club
ON city.id = club.city_id
WHERE club.published = 1
GROUP BY city.id, city.name, city.slug
HAVING club_count > 0