Given I have the following tables and records, I am interested in getting all the missions where the agency is both Nasa and Esa. I have written an inner join statement but I don't know how can I narrow this down to the result I am looking for. Just for your information I am using sqlite .
Missions Table
CREATE TABLE mission_agencies (
id INTEGER NOT NULL,
name VARCHAR(250),
PRIMARY KEY (id)
)
id name
1 m1
2 m2
3 m3
4 m4
5 m5
Mission Agencies Table
CREATE TABLE missions (
_id INTEGER NOT NULL,
name VARCHAR(36) NOT NULL,
PRIMARY KEY (_id)
)
id name
1 Nasa
2 Esa
3 Jax
Mission Ownership Table(The association table)
CREATE TABLE mission_ownership (
mission_id INTEGER,
mission_agency_id INTEGER,
FOREIGN KEY(mission_id) REFERENCES missions (id),
FOREIGN KEY(mission_agency_id) REFERENCES mission_agencies (id)
)
mission_id mission_agency_id
1 1
2 1
3 1
4 2
1 2
5 3
The current SQL statement I have is this:
SELECT *
FROM missions
INNER JOIN mission_ownership
ON missions._id = mission_ownership.mission_id
INNER JOIN mission_agencies
ON mission_agencies._id = mission_ownership.mission_agency_id
This produces a table like this:
id name mission_id mission_agency_id id name
1 m1 1 1 1 Nasa
2 m2 2 1 1 Nasa
3 m3 3 1 1 Nasa
4 m4 4 2 2 Esa
1 m1 1 2 2 Esa
5 m5 5 3 3 Jax
Now I like to run a query where I ask for all the missions that have been done by both Nasa AND Esa, and the only mission satisfying this criteria is m1
, so my target result set should look like this:
id name mission_id mission_agency_id id name
1 m1 1 1 1 Nasa
1 m1 1 2 2 Esa
How can I write such a query?
If you are running MySQL 8.0, here is an approach using window functions:
select *
from (
select *, count(*) over(partition by m.id) cnt
from missions m
inner join mo on m.id = mo.mission_id
inner join ma on ma.id = mo.mission_agency_id
where ma.name in ('Nasa', 'Esa')
) t
where cnt > 1
The idea is to filter your current resultset on the agencies that you are interested in, and count how many rows remain for each mission. We can then filter on missions that have both agencies.
Note that this assumes no duplicate mission/agency.
Following the idea of filtering and counting rows as suggested down here, I found a query that works like this:
SELECT COUNT(mid), mname
FROM(
SELECT missions._id AS mid, missions.name AS mname
FROM missions
INNER JOIN mission_ownership
ON missions._id = mission_ownership.mission_id
INNER JOIN mission_agencies
ON mission_agencies._id = mission_ownership.mission_agency_id
WHERE mission_agencies.name = 'Esa' or mission_agencies.name = 'Jax'
)
GROUP BY mid
HAVING COUNT(mid) > 1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.