Как объединить три таблицы в MySQL - PullRequest
1 голос
/ 06 ноября 2019

У меня есть три таблицы:

группа

id_group (PK) | name

registry_in_group

id_group (PK-FK) | id_registry (PK-FK)

реестр

id_registry (PK) | name | surname | dob (DATE)

Мне нужно выбрать имена групп, которые содержат только реестр с возрастом более 18 лет.

Это мой запрос:

SELECT g.name 
FROM group as g
JOIN registry_in_group as aig 
    ON g.id_group = aig.id_group
JOIN registry as a 
    ON aig.id_registry = a.id_registry 
    AND TIMESTAMPDIFF(YEAR, a.dob, CURDATE()) >= 18

Ноэто возвращение также реестра ниже 18. Почему?

1 Ответ

0 голосов
/ 06 ноября 2019

Проблема с вашим запросом состоит в том, что он находит группы, которые имеют хотя бы один реестр старше 18 лет, тогда как вы хотите убедиться, что все реестры в группе удовлетворяют этому условию.

Вы можете использовать коррелированный подзапрос с условием not exists для фильтрации по группам, для которых ни один реестр не моложе 18:

select g.*
from groups g
where not exists (
    select 1
    from registry_in_group rig
    inner join registry r 
        on  r.id_registry = rig.id_registry 
        and timestampdiff(year, r.dob, curdate()) < 18
    where rig.id_group = g.id_group
)

Другой вариант, основанный на вашем запросе, заключается в использовании агрегации с *Предложение 1009 * для фильтрации групп, содержащих реестр младше 18 лет:

select g.name 
from groups g
inner join registry_in_group rig 
    on g.id_group = rig.id_group
inner join registry r
    on rig.id_registry = r.id_registry 
group by g.id_group, g.name
having sum( timestampdiff(year, r.dob, curdate()) < 18 ) = 0

Примечание: как прокомментировал Strawberry, group - зарезервированное слово во всех СУБД;Вместо этого я использовал groups, чтобы избежать путаницы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...