SQL group_by и group_concat, если все значения присутствуют в группе - PullRequest
1 голос
/ 29 мая 2020
/*
 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

Найти все машины, помещенные во все запрошенные гаражи одновременно. Итак, я хочу достичь этого

---------------------------------------------------------
cars       |   garages
---------------------------------------------------------
BMW        | Garage1, Garage2, Garage3                 - RETURNED!!
Audi       | Garage1, Garage2, Garage3, Garage4        - RETURNED!!
Volkswagen | Garage1, Garage2,                 Garage4 - NOT returned because garage3 not present
---------------------------------------------------------

Я не знаю, как создать только один sql запрос

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

Ответы [ 2 ]

1 голос
/ 29 мая 2020

Ваша проблема называется Relational Division . Предполагая, что cars_location (car_id, garage_id) уникален:

select cars.name as cars,
       group_concat(
           garages.name
           ) as places
from cars_location  -- no Outer Joins needed as you don't wannt 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
1 голос
/ 29 мая 2020

Вы хотите предложение having:

having sum(garage.id = 1) > 0 and
       sum(garage.id = 2) > 0 and
       sum(garage.id = 3) > 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...