30.03.2020 gorm sql postgresql
Представим себе такую структуру сущностей:
type Parent struct { gorm.Model Name string } type Child struct { gorm.Model ParentID uint // child -> parent many to one link Name string }
Как теперь отфильтровать родителей по наличию связанных детей с определенными признаками?
В первую очередь мы думаем о JOIN и фильтрации, в GORM это реализуемо:
err := db.Model(&Parent{}).Joins( "LEFT JOIN children ON parents.id = children.parent_id AND children.name = ?", "somename", ).Find(&results).Error
Запрос полностью:
SELECT * FROM "parents" LEFT JOIN children ON parents.id = children.parent_id AND children.name = 'somename'
Однако минус данного решения очевиден — строки с данными родителей будут повторены несколько раз, если под фильтр подходит несколько детей (логичное поведение JOIN).
Следовательно, решение должно быть без JOIN, желательно добавить только where
.
Cледующий фрагмент работает:
err := db.Model(&Parent{}).Where( "EXISTS (SELECT 1 FROM children WHERE children.parent_id = parents.id AND children.name = ?)", "somename", ).Find(&results).Error
Полностью запрос выглядит так:
SELECT * FROM "parents" WHERE EXISTS (SELECT 1 FROM children WHERE children.parent_id = parents.id AND children.name = 'somename')