Мне кажется, я понял, что тебе нужно. Это заставило меня задуматься, спасибо! : -)
Я считаю, что эквивалентный SQL-запрос будет выглядеть примерно так:
select t.name, s.name, count(user_id) count_of_users
from yourapp_annot a, yourapp_tag t, yourapp_sample s
where a.tag_id = t.id
and s.id = a.sample_id
group by t.name, s.name
having count_of_users > 1
Хотя я стараюсь не думать о SQL, когда я придумываю навигацию по моделям django (это мешает); когда дело доходит до запросов агрегации, это всегда помогает мне увидеть, каким будет SQL.
В django у нас теперь есть агрегатов .
Вот что я придумал:
models.Annot.objects.select_related().values(
'tag__name','sample__name').annotate(
count_of_users=Count('user__id')).filter(count_of_users__gt=1)
Набор результатов будет содержать тег, образец и количество пользователей, которые пометили указанный образец с помощью указанного тега.
Разбить его на части для людей, которые не привыкли к агрегированию django:
models.Annot.objects.select_related()
- select_related () принудительно запрашивает все таблицы, относящиеся к Annot, в одном запросе
- Это то, что позволит мне указать
tag__name
и sample__name
в значениях (), вызов
values('tag__name','sample__name')
- values () ограничивает поля для извлечения до tag.name и sample.name
- Это гарантирует, что мое агрегирование по количеству клиентов будет группироваться только по этим полям
annotate(count_of_users=Count('user__id'))
- annotate () добавляет агрегацию в качестве дополнительного поля к запросу
filter(count_of_users__gt=1)
- И, наконец, я фильтрую по совокупному количеству.
Если вы хотите добавить дополнительный фильтр на то, какие пользователи должны учитываться, вам нужно сделать это:
models.Annot.objects.filter(user=[... list of users...]).select_related().values(
'tag__name','sample__name').annotate(
count_of_users=Count('user__id')).filter(count_of_users__gt=1)
Я думаю, что это так.
Одна вещь ... Обратите внимание, что я использовал tag__name и sample__name в запросе выше. Но ваши модели не указывают, что имена тегов и имена образцов уникальны .
Должны ли они быть уникальными? Добавьте unique=True
к определениям полей в моделях.
Разве они не должны быть уникальными? Вам нужно заменить tag__name и sample__name на tag__id и sample__id в запросе выше.