django - 通过聚合

时间:2017-07-25 11:30:30

标签: python django postgresql django-queryset django-jsonfield


我的模型包含来自data的{​​{1}}类型的字段JSONField。 json结构是这样的:

django.contrib.postgres.fields

我想汇总{'aa': 1, 'bb': 2, 'cc': 4} aa键的总和 - 所以在这种情况下,它将是5.另外 - 我不能保证cc或{{1将在json中。
这可能吗?如果是这样 - 我想按汇总数据排序。
例如:

  1. id:1,data = {' aa':1,' bb':2,' cc':4}
  2. id:2,data = {' aa':3,' bb':2}
  3. id:3,data = {' cc':7}
  4. id:4,data = {' bb':7}
  5. 我想做一个查询,例如:
    aa
    聚合后,查询集中的有序行将为:

    1. id:3
    2. id:1
    3. id:2
    4. id:4
    5. 谢谢!

2 个答案:

答案 0 :(得分:2)

我知道你想要为每一行总结一个值和一个b值,然后按和值对每一行进行排序。正确?

-> ->>这是如何在PostgreSQL中选择JSON格式的键或值(我不知道它是否也适用于MySQL或其他,我通常使用PostgreSQL)。 here中有很好的资源。您的数据位于名为' data'的列中是{"aa":3, "bb":2, "cc":5}。所以你按data->>'aa'选择一个值。如果{'classification':{'pc':5000}}怎么办?你需要选择个人电脑价值。然后data->'classification'->>'pc'

:: notation是强制转换操作。

CAST(data->'aa' AS INTEGER)

data->'aa'::int

类RawSQL(sql,params,output_field = None)

RawSQL("((data->>' aa' :: int),(0,)")并不意味着如果aa没有&# 39; t存在,它有0值.0是params。

queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

好吧,如果您可以像这样修改数据

  • id:1,data = {' aa':1,' bb':2,' cc':4}
  • id:2,data = {' aa':3,' bb':2,' cc':0}
  • id:3,data = {' cc':7,' bb':0,' cc':0}
  • id:4,data = {' bb':7,' bb':0,' cc':0}

这可行。

Contract.objects.annotate(
sumVal=RawSQL("((data->>'aa')::int)", (0,))+RawSQL("((data->>'cc')::int)",(0,)))
.order_by('sumVal')

我建议使用Coalesce。这个问题的作者想通了。下面有代码。

raw_sql = "+".join(["COALESCE((data->>%s)::int, 0)" for _ in ['aa', 'cc']) 
MyMoodel.objects.all()
.annotate(my_sum=RawSQL(raw_sql, params=('aa', 'cc')))
.order_by('my_sum')

答案 1 :(得分:1)

 YourModel.objects.annotate(aa=RawSQL("((data->>'aa')::int)", (0,)),
                            cc=RawSQL("((data->>'cc')::int)", (0,))) \
                .aggregate(total=Sum('aa')+Sum('cc')).order_by('total')