Группировка и подсчет количества детей, когда у каждого ребенка больше определенного количества детей.

У меня есть три модели, Business, Employee и Client, где каждый бизнес может иметь много сотрудников и каждый сотрудник может иметь много клиентов:

class Business(models.Model):
    name = models.CharField(max_length=128)
    menu = models.CharField(max_length=128, default="")
    slogan = models.CharField(max_length=128, default="")
    slug = models.CharField(max_length=128, default="")


class Employee(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    business = models.ForeignKey(
        Business,
        related_name="employees",
        on_delete=models.CASCADE
    )


class Client(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    employee = models.ForeignKey(
        Employee,
        related_name="clients",
        on_delete=models.CASCADE
    )

Пример данных:

Business.objects.create(name="first company")
Business.objects.create(name="second company")
Business.objects.create(name="third company")
Employee.objects.create(first_name="f1", last_name="l1", business_id=1)
Employee.objects.create(first_name="f2", last_name="l2", business_id=1)
Employee.objects.create(first_name="f3", last_name="l3", business_id=2)
Employee.objects.create(first_name="f4", last_name="l4", business_id=3)
Employee.objects.create(first_name="f5", last_name="l5", business_id=3)
Employee.objects.create(first_name="f6", last_name="l6", business_id=3)
Client.objects.create(first_name="cf1", last_name="cl1", employee_id=1)
Client.objects.create(first_name="cf2", last_name="cl2", employee_id=1)
Client.objects.create(first_name="cf3", last_name="cl3", employee_id=2)
Client.objects.create(first_name="cf4", last_name="cl4", employee_id=2)
Client.objects.create(first_name="cf5", last_name="cl5", employee_id=3)
Client.objects.create(first_name="cf6", last_name="cl6", employee_id=3)
Client.objects.create(first_name="cf7", last_name="cl7", employee_id=4)
Client.objects.create(first_name="cf8", last_name="cl8", employee_id=5)
Client.objects.create(first_name="cf9", last_name="cl9", employee_id=6)

Если бы я хотел узнать, сколько сотрудников работает на каждом предприятии, я мог бы выполнить такой запрос:

Business.objects.annotate(
    employee_count=Count("employees")
).values(
    "name", "employee_count"
).order_by("-employee_count")

<QuerySet [
    {'name': 'third company', 'employee_count': 3},
    {'name': 'first company', 'employee_count': 2},
    {'name': 'second company', 'employee_count': 1}
]>

Аналогично, если бы я хотел узнать, сколько клиентов у каждого сотрудника, я мог бы выполнить такой запрос:

Employee.objects.annotate(
    client_count=Count("clients")
).values(
    "first_name", "client_count"
).order_by("-client_count")

<QuerySet [
    {'first_name': 'f1', 'client_count': 2},
    {'first_name': 'f2', 'client_count': 2},
    {'first_name': 'f3', 'client_count': 2},
    {'first_name': 'f4', 'client_count': 1},
    {'first_name': 'f5', 'client_count': 1},
    {'first_name': 'f6', 'client_count': 1}
]>

Но я хочу видеть для каждого предприятия количество сотрудников, которые имеют более одного клиента. Я ожидаю получить результат следующего вида:

<QuerySet [
    {'name': 'first company', 'employee_count': 2},
    {'name': 'second company', 'employee_count': 1},
    {'name': 'third company', 'employee_count': 0}
]>

Я попытался использовать Count с Subquery, но результат не тот, который я ожидал.

employees_with_multiple_clients = Employee.objects.annotate(
    client_count=Count("clients")
).filter(client_count__gt=1)


Business.objects.annotate(
    employee_count=Count(Subquery(employees_with_multiple_clients.values('id')))
).values("name", "employee_count").order_by("-employee_count")


<QuerySet [
    {'name': 'first company', 'employee_count': 1},
    {'name': 'second company', 'employee_count': 1},
    {'name': 'third company', 'employee_count': 1}]>

Как я могу получить для каждого предприятия количество сотрудников, имеющих более одного клиента?

Чтобы узнать, сколько предприятий имеют сотрудников более одного клиента, вы можете попробовать:

employees_with_multiple_clients = Employee.objects.annotate(
    client_count=Count("clients")
).filter(business=OuterRef('pk'), client_count__gt=1)

employees = employees_with_multiple_clients.annotate(c=Count('*')).values('c')

Business.objects.annotate(
    employee_count=Subquery(employees).values("name", "employee_count").order_by("-employee_count")

Я использую тот же подход здесь, я фильтрую, используя счетчик client_count на основе бизнеса (используя OuterRef), а затем снова подсчитываю при аннотации с помощью Subquery.

Вернуться на верх