然后提取月份和年份,然后使用Django ORM进行计数并得到分组平均值

问题描述 投票:0回答:1

我想提取年份和月份。然后我想按年,月和区分组,然后计算行数并计算每组的平均价格。实际上,下面的SQL语句可以完成我想做的事情。那么,我该如何使用Django ORM?

SELECT district, month, year, COUNT(ilan_no) , TO_CHAR(AVG(price), '9999999999') as avg_price
FROM (
    SELECT 
    ilan_no,
    district,
    price,
    EXTRACT (MONTH FROM add_date) as month,
    EXTRACT (YEAR FROM add_date) as year     
    FROM ilan) as foo
GROUP BY district, month, year
ORDER BY year, month, district

models.py:

class Ilan(models.Model):
    ilan_no = models.IntegerField(unique=True, blank=True, null=True)
    url = models.CharField(unique=True, max_length=255, blank=True, null=True)
    add_date= models.DateField()
    origin = models.CharField(max_length=100, blank=True, null=True)
    city = models.CharField(max_length=20, blank=True, null=True)
    district = models.CharField(max_length=30, blank=True, null=True)
    price = models.IntegerField(blank=True, null=True)

serializers.py:

class IlanSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ilan
        fields = ['ilan_no', 'add_date', 'district', 'price']

我在下面尝试过queryset,但是value()方法不适用于Rest-Framework序列化程序。

view.py:

class IlcePriceAndSizeDistributionListView(ListAPIView):
    queryset = Ilan.objects.annotate(year=ExtractYear('add_date')).annotate(month=ExtractMonth('add_date')).values('district', 'year', 'month', 'ilan_no', 'add_date', 'price').annotate(
        ortalama_m2=Avg('m2_net')).annotate(ortalama=Avg('price')).annotate(count=Count('ilan_no')).order_by('year', 'month')
    serializer_class = IlanSerializer
python django django-rest-framework django-orm
1个回答
0
投票

尝试这种方式,让我知道以后是否可以使用。

from django.db.models import F, Q, Avg, Subquery, OuterRef, Count, IntegerField
from django.db.models.functions import ExtractMonth, ExtractYear
q = Ilan.objects.annotate(
        month=ExtractMonth('add_date'),
        year=ExtractYear('add_date')
    ).values('district','month','year')

qsub = q.filter(
            Q(district=OuterRef('district')),
            Q(month=OuterRef('month')),
            Q(year=OuterRef('year')),
        )

qset = q.annotate(count = Subquery(
            qsub.annotate(num = Count('year')).values('num'), 
            output_field = IntegerField)
        ).annotate(avg_price = Subquery(
            qsub.annotate(avg = Avg('price').values('avg'),
            output_field = IntegerField)
        )
    ).order_by('year', 'month', 'district')

生成的sql:

SELECT "myapp_ilan"."district",
       django_date_extract('month', "myapp_ilan"."add_date") AS "month",
       django_date_extract('year', "myapp_ilan"."add_date") AS "year",

  (SELECT U0."district",
          django_date_extract('month', U0."add_date") AS "month",
          django_date_extract('year', U0."add_date") AS "year",
          COUNT(django_date_extract('year', U0."add_date")) AS "num"
   FROM "myapp_ilan" U0
   WHERE (U0."district" = ("myapp_ilan"."district")
          AND django_date_extract('month', U0."add_date") = (django_date_extract('month', "myapp_ilan"."add_date"))
          AND django_date_extract('year', U0."add_date") = (django_date_extract('year', "myapp_ilan"."add_date")))
   GROUP BY U0."district",
            django_date_extract('month', U0."add_date"),
            django_date_extract('year', U0."add_date")) AS "count",

  (SELECT U0."district",
          django_date_extract('month', U0."add_date") AS "month",
          django_date_extract('year', U0."add_date") AS "year",
          COUNT(U0."price") AS "avg"
   FROM "myapp_ilan" U0
   WHERE (U0."district" = ("myapp_ilan"."district")
          AND django_date_extract('month', U0."add_date") = (django_date_extract('month', "myapp_ilan"."add_date"))
          AND django_date_extract('year', U0."add_date") = (django_date_extract('year', "myapp_ilan"."add_date")))
   GROUP BY U0."district",
            django_date_extract('month', U0."add_date"),
            django_date_extract('year', U0."add_date")) AS "avg_price"
FROM "myapp_ilan"
ORDER BY "year" ASC,
         "month" ASC,
         "myapp_ilan"."district" ASC
© www.soinside.com 2019 - 2024. All rights reserved.