我正在执行此查询:
SomeObject.objects.annotate(something=Avg('something')).order_by(something).all()
我的模型中通常有一个聚合字段,我将其与 Django 信号一起使用以保持同步,但是在这种情况下,性能不是问题,所以我认为我应该保持简单,只使用子查询。
然而,这种方法带来了一个意想不到的问题。 如果聚合函数结果如下所示,那么一切都很好:
[5.0, 4.0, 6.0 … (etc, just numbers)]
但是,如果您混合一些None
,那么它的顺序如下:
[None, 5.0, 4.0 …]
问题是 None 的值比任何数字都高,而它的值最多应该为 0。
我正在使用 PostgreSQL,尚未测试其他数据库。我实际上还没有检查生成了什么查询等。
我通过在内存中排序来解决这个问题:
sorted(…, key=lambda _:_.avg_rating if _.avg_rating is not None else 0)
所以我只是好奇是否有办法只用 Django ORM 来做到这一点?也许.where
?还是别的什么?
最佳答案
通过 extra() 添加 has_something=1,0 然后对 has_something 和 some 进行排序怎么样?
with_avg = SomeObject.objects.annotate(avg=Avg('something'))
with_avg_and_has = with_avg.extra(select={'has_something': 'something is NULL'})
sorted_result = with_avg_and_has.order_by('-has_something', '-avg').all()
严格意义上不是 100% ORM,但它确实将排序推回到数据库中。
关于python - Django ORM : Ordering w/aggregate functions — None special treatment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2572201/