Вопрос

У меня возникли проблемы с написанием запроса для следующих классов домена:

class Person {
  static hasMany = [memberships: Membership]
}

class Membership {

    static belongsTo = [person: Person, group: Group]

    Date joinDate = new Date();
    Group group;
    Person person;
}

class Group {
     static hasMany = [memberships: Membership]
}

По сути, я хочу найти всех людей, принадлежащих к списку групп (скажем, идентификаторы групп (1,2).Хитрость здесь в том, что человек должен быть членом обеих групп.Я бы предпочел запрос по критериям, но HQL тоже подойдет.

Обратите внимание, что запрос с чем-то вроде group.id in (1,2) не сработает, потому что это может быть любая из групп, а не оба.

Это было полезно?

Решение

Это мой простой подход HQL:

Person.executeQuery("FROM Person x WHERE x IN (SELECT m.person from Membership m WHERE m.group = :group1) AND x IN (SELECT m.person from Membership m WHERE m.group = :group2)", [ group1: Group.get(1), group2: Group.get(2) ])

Ваше здоровье

Другие советы

Возможно, вам не нужен запрос.В классе Person членство представляет собой список объектов Membership.Вы можете узнать, находится ли объект в коллекции (списке), не делая никаких запросов.Что-то вроде этого должно сработать.

if(Person.memberships.contains(Membership.findByPersonAndGroup(person1,group1)) && Person.memberships.contains(Membership.findByPersonAndGroup(person1,group2))){
  ...do something...
}

Вероятно, другое решение проще, но я думаю, что это просто еще один вариант.

Ваше здоровье

Отличные коллекции

Интересная проблема.Не уверен, что предыдущие решения являются общими по количеству совпадающих групп - я думаю, что на данный момент оно зафиксировано на уровне 2.Хотя, наверное, есть способ сделать их переменными.

Другой способ, который я описываю здесь, на доске объявлений Grails - http://www.nabble.com/has-many-through-relationship-query---GORM--td23438096.html

Включая комментарий автора Роберта Фишера «Сохраняемость Grails с помощью GORM и GSQL».

@chadsmall

Вот еще один подход, позволяющий избежать необходимости программного добавления подзапросов к предложению WHERE:

Запрос:

SELECT count(person.id) AS numPeople, person 
FROM Person as person 
INNER JOIN 
person.memberships AS mships
WITH mships.group.id IN (:groupIds) 
GROUP BY person.id 
HAVING COUNT(person.id) = (:numOfGroupIds)

И несколько примеров значений:

[
  groupIds: [8,9,439,86843]
  numOfGroupIds: 4
]

Часть этого запроса до GROUP BY собирает всех людей, которые соответствуют любой групп.Затем, сгруппировав по человеку и проверив, что количество результатов равно количеству групп в списке, вы можете убедиться, что этот человек является членом всех указанных групп.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top