Ami*_*Ami 11 django orm model average rounding
我有一个模型,我使用Django ORM从表中提取平均值.我想要舍入Avg值,我该怎么做?
请参阅下文我从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')
Run Code Online (Sandbox Code Playgroud)
mrt*_*rts 32
使用Func()表达式.
以下是使用Django Aggregation主题指南中的Book模型在SQLite中舍入到两个小数位的示例:
class Round(Func):
function = 'ROUND'
template='%(function)s(%(expressions)s, 2)'
Book.objects.all().aggregate(Round(Avg('price')))
Run Code Online (Sandbox Code Playgroud)
这允许参数化圆函数(来自@ RichardZschech的答案):
class Round(Func):
function = 'ROUND'
arity = 2
Book.objects.all().aggregate(Round(Avg('price'), 2))
Run Code Online (Sandbox Code Playgroud)
改进@mrts答案.
这允许参数化圆函数:
class Round(Func):
function = 'ROUND'
arity = 2
Book.objects.all().aggregate(Round(Avg('price'), 2))
Run Code Online (Sandbox Code Playgroud)
基于以前的答案,我来到这个解决方案,使其适用于PostgreSQL:
from django.db.models import Func
class Round2(Func):
function = "ROUND"
template = "%(function)s(%(expressions)s::numeric, 2)"
# Then use it as ,e.g.:
# queryset.annotate(ag_roi=Round2("roi"))
# qs.aggregate(ag_sold_pct=Round2(Sum("sold_uts") / (1.0 * Sum("total_uts"))) * 100
Run Code Online (Sandbox Code Playgroud)
我需要同时支持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))
Run Code Online (Sandbox Code Playgroud)
我更喜欢更干净的东西,比如
if SQLITE:
arg_joiner=", "
elif PGSQL:
arg_joiner = '::numeric, '
else raise NotImplemented()
Run Code Online (Sandbox Code Playgroud)
但没找到怎么样,欢迎改进!
| 归档时间: |
|
| 查看次数: |
6643 次 |
| 最近记录: |