You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Peewee框架fn.AVG()返回int而非预期float的问题排查

Peewee中fn.AVG()返回int而非float的原因分析

问题场景

  • 使用SQLite数据库,models.Mark.skill字段定义为IntegerField
  • 直接执行原生SQL查询:
    SELECT players.name, AVG(marks.skill) FROM players 
    JOIN marks ON player_id = players.id 
    GROUP BY players.id;
    
    得到正确浮点结果:
    Charname | 6.6
    
  • 但通过Peewee执行查询时:
    from peewee import *
    import models
    
    query = (
        models.Player.select(
            models.Player.name,
            fn.AVG(models.Mark.skill).alias('skill'),
        )
        .join(models.Mark, JOIN.LEFT_OUTER)
        .group_by(models.Player.id)
    )
    
    for q in query:
        print(q.name, q.skill, type(q.skill))
    
    结果被截断为int类型:
    Charname 6 int
    

核心原因

Peewee会根据被聚合字段的类型自动推断聚合结果的解析类型:

  1. SQLite的AVG()函数对整数列计算时,会返回REAL(浮点)类型,这是数据库本身的特性,所以原生SQL能得到正确结果。
  2. 但Peewee的类型绑定逻辑中,当聚合函数作用于IntegerField时,框架默认使用整数类型的转换器处理结果,直接将SQLite返回的浮点值强制转换为int,截断了小数部分。

解决方向

可以通过显式指定结果类型来修正:

方法1:用SQL的CAST转换结果

query = (
    models.Player.select(
        models.Player.name,
        fn.CAST(fn.AVG(models.Mark.skill), 'REAL').alias('skill'),
    )
    .join(models.Mark, JOIN.LEFT_OUTER)
    .group_by(models.Player.id)
)

方法2:用Peewee的cast()方法指定字段类型

from peewee import FloatField

query = (
    models.Player.select(
        models.Player.name,
        fn.AVG(models.Mark.skill).cast(FloatField()).alias('skill'),
    )
    .join(models.Mark, JOIN.LEFT_OUTER)
    .group_by(models.Player.id)
)

内容的提问来源于stack exchange,提问作者Artem Ermakov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 11:30:57