Reputation: 997
/*
cars cars_location
+------+---------+ +-------------+-----+ garages
| id | int |<---| car_id | int | +-------+---------+
| name | varchar | | garage_id | int | --->| id | int |
+------+---------+ +-------------+-----+ | name | varchar |
+-------+---------+
*/
drop table if exists cars, garages, cars_location;
create table cars
(
id int not null,
name varchar(255),
primary key (id)
);
create table garages
(
id int not null,
name varchar(255),
primary key (id)
);
create table cars_location
(
car_id int not null,
garage_id int not null,
primary key (car_id, garage_id)
);
insert into cars (id, name)
values (1, 'BMW'),
(2, 'Audi'),
(3, 'Volkswagen');
insert into garages (id, name)
values (1, 'Garage1'),
(2, 'Garage2'),
(3, 'Garage3'),
(4, 'Garage4');
insert into cars_location (car_id, garage_id)
values (1, 1),
(1, 2),
(1, 3),
(2, 1),
(2, 2),
(2, 3),
(2, 4),
(3, 1),
(3, 2),
(3, 4);
-- Find all cars placed in all requested garages at the same time.
-- Example below:
/*
---------------------------------------------------------
cars | garages
---------------------------------------------------------
BMW | Garage1, Garage2, Garage3 - RETURNED!!
Audi | Garage1, Garage2, Garage3, Garage4 - RETURNED!!
Volkswagen | Garage1, Garage2, Garage4 - NOT returned
---------------------------------------------------------
*/
select cars.name as cars,
group_concat(
garages.name
) as places
from cars_location
left join cars on cars.id = cars_location.car_id
left join garages on garages.id = cars_location.garage_id
-- where places in (1,2,3) # problem here because Volkswagen doesnt exist in garage 3 so should not be visible
group by 1
Find all cars placed in all requested garages at the same time. So I want to achieve this
---------------------------------------------------------
cars | garages
---------------------------------------------------------
BMW | Garage1, Garage2, Garage3 - RETURNED!!
Audi | Garage1, Garage2, Garage3, Garage4 - RETURNED!!
Volkswagen | Garage1, Garage2, Garage4 - NOT returned because garage3 not present
---------------------------------------------------------
I dont know how to build only one sql query
select cars.name as cars,
group_concat(
garages.name
) as places
from cars_location
left join cars on cars.id = cars_location.car_id
left join garages on garages.id = cars_location.garage_id
-- where places MUST BE in (1,2,3) # problem here because Volkswagen doesnt exist in garage 3 so should not be returned by sql
group by 1
http://sqlfiddle.com/#!9/eadd7a/1
Upvotes: 1
Views: 56
Reputation: 60472
Your problem is called Relational Division. Assuming cars_location (car_id, garage_id)
is unique:
select cars.name as cars,
group_concat(
garages.name
) as places
from cars_location -- no Outer Joins needed as you don't want non-matching locations
join cars on cars.id = cars_location.car_id
join garages on garages.id = cars_location.garage_id
where garages.id in (1,2,3)
group by 1
having count(*) = 3 -- exactly three rows
Upvotes: 1
Reputation: 1269803
You want a having
clause:
having sum(garage.id = 1) > 0 and
sum(garage.id = 2) > 0 and
sum(garage.id = 3) > 0
Upvotes: 1