MySQL - writing joins to get data from many-layers linked tables - mysql

I'm having trouble writing the query for this specific task. Here are the simplified tables:
`job`: job_id, school_id
`school`: school_id, country_id
`country`: country_id, region_id
`region`: region_id, region
Now, I'm querying the job table to get the jobs listing, but I also need to show each job's region (i.e. Europe, Asia, etc.)
How do I do so giving these linked tables?

from what you provide it looks like this:
select
*
from `job` j
inner join `school` s on j.school_id = s.school_id
inner join `country`c on s.country_id = c.country_id
inner join `region` r on c.region_id = r.region_id
But I think the school table should hold region, or, country and region.

Related

INNER JOIN mysql return nothing

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

How to filter the output based on the output of count in MySQL?

Tables in my database: 1. Employee
2.Aircraft
3.Certified
Query: I need to find pilot name, eid, aircraft name, cruising_range where pilot is certified to fly more than 3 aircraft's . i wrote a query and it works but i want to know if there is a simple way to achieve this because my query seems much complicated .
My query is :
Edit: Corrected the name of tables.
If you can assume that each AID in Certified had a corresponding value on Aircraft, then it can be done like this:
SELECT ename,employee.eid,aname,crusing_range
FROM employee JOIN certified
ON employee.eid = certified.eid
JOIN aircraft
ON certified.aid = aircraft.aid
WHERE exists(select 1 FROM certified t
WHERE t.eid = employee.eid
GROUP BY t.eid HAVING COUNT(*) >= 3)
Ahh man, don't prefix your columns with your table names. Just have employee ID column as id not eid
I would try this:
SELECT <columns>
FROM aircraft A
LEFT JOIN employee E ON E.eid = A.eid
LEFT JOIN certified C ON C.aid = A.aid
Where SUM(A.eid) > 3
I'm on mobile but I hope it helps.
The key information is in the Aircraft table so start with that and then join the tables you want the extra bits from. Chucking a distinct on employee id within the SELECT will stop duplicates too.
Rethink table names too.

How can I build MySQL query with additional column equals to number of associated rows?

Let's say I have two tables Cities and Employees. Each employee associated with one city. How can I build a query resulting with all cities and will have additional column equals to number of employees associated with this city?
I tried the following:
SELECT *,COUNT(SELECT * FROM `Employees` WHERE `city_id` = `id`) AS `count` FROM `cities`
But it's not working.
Actually I have no idea where I should looking for. Hope that I will have any hint here.
You may try the following query using inner join between cities and employees table
SELECT cities.* ,COUNT( `Employees`.`id`) FROM `cities`
INNER JOIN `Employees` on `Employees`.`city_id` = `cities`.`id`
GROUP BY `cities`.`id`
If you prefer old style SQL you could try something like this
SELECT cityTable.`name`, employeesTable.employees_count
FROM (SELECT `id`, `name` FROM `Cities`)citiesTable,
(SELECT count(*) as employees_count, `city_id` FROM `Employees`)employeesTable
WHERE citiesTable.`id` = employeesTable.`city_id`
The predicate is: Give me all cities, and the number of employees belonging to them.
SELECT c.name, COUNT(e.id) cnt
FROM cities c
LEFT JOIN employees e
ON c.id = e.city_id
GROUP BY c.name
This will give you all cities with cnt zero if a city has no employees belonging to it

SQL (mysql) query improvement

First of all, let me explain my data structure.
I have a model called profile, witch is a profile for a service provider. The service provider may choose from two diferent types of "travels" (both and none of them also). The first travel mode is "I can go to the client". For that, the service provider needs to input all cities he can travel for (many-to-many). The second "travel" mode is "My client can come to me". Those, he chooses the city he is placed from a list (one-to-many).
For the "I can go to the client" travel mode, I have a locals_profile table with a profile_id and a local_id and a locals table with the city name.
For the "My client can come to me", I have a locations table with profile_id and city_id and a cities table with the name of the city.
Before you ask, because of other things in the project modeling, I couldn't use the same table for the city name in both cases (if I could, the performance would be increased?).
Also, the profile belongs to many sub_categories, witch bring us another table called profiles_sub_categories with sub_category_id and profile_id field.
What I want is, given a sub_category, show how many items I have in each city. Eg:
For the "designers" sub category:
New york (100)
San Fracisco (50)
Miami (10)
... (max 10 cities)
I've acomplished what I wanted with the following query:
select q1.city_name, if(q1.city_count is null, 0, q1.city_count) + if(q2.city_count is null, 0, q2.city_count) city_count
from
(select l.name as city_name, count(*) as city_count from locals_profiles lp
inner join locals l on l.id = lp.local_id
inner join profiles p on p.id = lp.profile_id
inner join profiles_sub_categories ps on ps.profile_id = p.id
where ps.sub_category_id = 97 and l.level = 2
group by 1) q1
left join
(select c.name as city_name, count(*) as city_count from cities c
inner join locations lo on lo.city_id = c.id
inner join profiles p on lo.profile_id = p.id
inner join profiles_sub_categories ps on ps.profile_id = p.id
where ps.sub_category_id = 97
group by 1) q2
on q1.city_name = q2.city_name
order by 2 DESC
limit 10;
But the query is taking too long to be executed. Since it's a web application, I need it to be almost instantly. Does anyone knows a better way to do what I'm trying?
I've found mysql doesn't do a great job of optimizing queries. The easy solution is writing two queries and merging them in the application layer. Suprisingly, it will probably be faster...
Alternatively, you could try eliminating the views (q1,q2) and aliasing the same tables multiple times instead. Might be tough to get right....

MySQL Join Query

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