Подсчет все Doctor
с за Specialization
Я думаю, что вы усложняете ситуацию, возможно потому, что вы думаете, что Count('doctor')
будет подсчитывать каждого врача за специализацию (независимо от специализации этого врача). Если у вас Count
такой связанный объект, нет, Django неявно ищет связанных объектов. На самом деле вы не можете Count('unrelated_model')
вообще, только через отношения (включая обратные), такие как ForeignKey
, ManyToManyField
и т. Д., Вы можете запросить их, поскольку в противном случае они не очень чувственные .
Я хотел бы аннотировать все специализации в наборе запросов с количеством врачей, которые имеют эту специализацию.
Вы можете сделать это с помощью простого:
# Counting all doctors <i>per</i> specialization (so not <i>all</i> doctors in general)
from django.db.models import <b>Count</b>
Specialization.objects.annotate(
<b>num_doctors=Count('doctor')</b>
)
Теперь каждый Specialization
объект в этом наборе запросов будет иметь дополнительный атрибут num_doctors
, представляющий собой целое число (количество врачей этой специализации).
Вы также можете фильтровать по Specialization
s в том же запросе (например, получить только специализации, оканчивающиеся на 'my'
). Пока вы не фильтруете соответствующий набор doctor
, Count
будет работать (см. Раздел ниже, как это сделать).
Если, однако, вы отфильтруете соответствующие doctor
s, то соответствующие подсчеты отфильтруют этих врачей. Кроме того, если вы отфильтруете другой связанный объект, то это приведет к дополнительному JOIN
, который будет действовать как множитель для Count
s. В этом случае может быть лучше использовать num_doctors=Count('doctor', distinct=True)
. Вы всегда можете использовать distinct=True
(независимо от того, делаете ли вы дополнительные JOIN
с или нет), но это окажет небольшое влияние на производительность.
Сказанное выше работает, потому что Count('doctor')
не просто добавляет всех докторов к запросу, оно делает LEFT OUTER JOIN
в таблице doctor
s и таким образом проверяет, что specialization_id
этого Doctor
это именно то, что мы ищем. Таким образом, запрос Django будет выглядеть так:
SELECT specialization.*
COUNT(doctor.id) AS num_doctors
FROM specialization
LEFT OUTER JOIN doctor <b>ON doctor.specialization_id = specialization.id</b>
GROUP BY specialization.id
То же самое с подзапросом даст функциональные результаты, но если Django ORM и система управления базами данных не найдут способ оптимизировать это, это может привести к дорогостоящему запросу, поскольку для каждой специализации может привести к дополнительному подзапросу в базе данных.
Подсчет удельный Doctor
с за Specialization
Скажите, однако, что вы хотите считать только врачей, чье имя начинается с Джо , тогда вы можете добавить фильтр на соответствующий doctor
, как:
# counting all Doctors with as name Joe per specialization
from django.db.models import Count
Specialization.objects.filter(
<b>doctor__name__startswith='Joe'</b> # sample filter
).annotate(
num_doctors=Count('doctor')
)