Не знаю, как сделать сложный SQL запрос в django

У меня есть эти две модели ниже

class Category(models.Model):
    
    id = models.AutoField(primary_key=True)
    cate_id = models.CharField(max_length=16, editable=False, default=utils.generate_random_str)
    name = models.CharField(max_length=64, default="")

class Record(models.Model):
    id = models.AutoField(primary_key=True)
    record_id = models.CharField(max_length=16, editable=False, default=utils.generate_random_str)
    count = models.IntegerField(blank=True)
    user = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)

А я хочу сделать SQL-запрос, отличающий cate_id и суммирующий их значения и группирующий их следующим образом:

SELECT B.name ,SUM(A.count) AS count_sum FROM app_record AS A, app_category AS B WHERE A.`user_id` = 1 AND B.cate_id IN (SELECT DISTINCT(B.cate_id) FROM app_record AS C, app_category AS D WHERE C.category_id = D.id ) AND A.category_id = B.id GROUP BY B.cate_id;

Я ожидаю, что результаты должны быть такими:

+---------+-----------+
| name    | count_sum |
+---------+-----------+
| Test1   |    494    |
| Test2   |    18     |
| Test3   |    269    |
+---------+-----------+
3 rows in set (0.001 sec)

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

Record.objects.filter(user=user).distinct().annotate(record__category_id=F('category__id')).aggregate(count_sum=Sum('count'))

Я не знаю, как это сделать, надеюсь, кто-нибудь сможет решить эту проблему. Большое спасибо.

Если вы хотите подсчитать сумму всех записей, и вам нужен агрегат, вы можете сделать это. Я не уверен, что totalcount является фактическим итогом из-за .distinct(), поэтому если код не подходит вам, попробуйте сначала удалить .distinct(), а затем попробовать снова. :)

Record.objects.filter(user=user)\
    .distinct()\
    .annotate(total_count=Count('count'))\
    .aggregate(count_sum=Sum('total_count')) 

Следующий код не нужен. Django автоматически включает id связанных моделей:

.annotate(record__category_id=F('category__id'))

как указано в этом документе

Получение отличных значений из полей в mysql без использования .distinct('category__id')

Record.objects.filter(user=user).values(category__id)\
    .annotate(
        count_ref=models.F('count')
    ).aggregate(
        total_count=models.Sum('count_ref')
    )
# maybe using just 'count' works, instead of count_ref, without the annotation. This is how I use the code, this is how it works for me.
Вернуться на верх