Eu tenho três mesas:
grupo
id_group (PK) | name
registry_in_group
id_group (PK-FK) | id_registry (PK-FK)
registro
id_registry (PK) | name | surname | dob (DATE)
Tenho que selecionar nomes de grupos que contenham apenas registros com idade superior a 18 anos.
Esta é a minha consulta:
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
Mas esse retorno também registro menor 18. Por quê?
O problema com sua consulta é que ela encontra os grupos que têm pelo menos um registro com mais de 18 anos, enquanto você deseja garantir que todos os registros no grupo cumpram essa condição.
Você pode usar uma subconsulta correlacionada com uma not exists
condição para filtrar os grupos para os quais nenhum registro é menor que 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
)
Outra opção, baseada em sua consulta, é usar a agregação com uma having
cláusula para filtrar os grupos que contêm um registro com menos de 18 anos:
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
NB: conforme comentado por Strawberry, group
é uma palavra reservada em todos os RDBMS; Usei em groups
vez disso, para evitar confusão.
Este artigo é coletado da Internet.
Se houver alguma infração, entre em [email protected] Delete.
deixe-me dizer algumas palavras