Django ORM如何舍入平均结果

时间:2012-12-10 01:23:35

标签: django orm model rounding average

我有一个模型,我使用Django ORM从表中提取平均值。我想围绕平均值,我该怎么做?

见下文我从YYYY-MM格式的按日期分组的价格模型中提取平均价格,我想自动提取四舍五入到最接近数字的平均值。

rs = Prices.objects.all.extra(select={
    'for_date': 'CONCAT(CONCAT(extract( YEAR from for_date ), "-"),
        LPAD(extract(MONTH from for_date), 2, "00"))'
    }).values('for_date').annotate(price=Avg('price')).order_by('-for_date')

5 个答案:

答案 0 :(得分:32)

使用Func() expressions

以下是使用Django Aggregation topic guide中的Book模型在SQLite中舍入到小数点后两位的示例:

class Round(Func):
    function = 'ROUND'
    template='%(function)s(%(expressions)s, 2)'

Book.objects.all().aggregate(Round(Avg('price')))

这允许参数化圆函数(来自@ RichardZschech的答案):

class Round(Func):
  function = 'ROUND'
  arity = 2

Book.objects.all().aggregate(Round(Avg('price'), 2))

答案 1 :(得分:8)

改进@mrts答案。

这允许参数化圆函数:

class Round(Func):
  function = 'ROUND'
  arity = 2

Book.objects.all().aggregate(Round(Avg('price'), 2))

答案 2 :(得分:5)

基于先前的答案,我来到了此解决方案以使其适用于 PostgreSQL

select * from 
(SELECT 'N/A' as title,0 as ord FROM [Games] 
UNION 
SELECT [Games].[Title],1 as ord FROM Games)a
order by ord,title

答案 3 :(得分:1)

我需要同时具有 PostgreSQL SQLite 的支持,而且还需要能够指定要保留的位数。

基于先前的答案:

class Round(Func):
    function = 'ROUND'
    arity = 2
    # Only works as the arity is 2
    arg_joiner = '::numeric, '

    def as_sqlite(self, compiler, connection, **extra_context):
        return super().as_sqlite(compiler, connection, arg_joiner=", ", **extra_context)

# Then one can use it as:
# queryset.annotate(avg_val=Round(AVG("val"), 6))

我本来希望更清洁的东西

if SQLITE:
    arg_joiner=", "
elif PGSQL:
    arg_joiner = '::numeric, '
else raise NotImplemented()

但没有找到方法,随时可以改善!

答案 4 :(得分:1)

Django具有Round函数。有关更多详细信息,请参见the documentation