SQLAlchemy中如何将布尔列转为整数计算平均值?
解决SQLAlchemy中布尔类型转整数求平均的问题
这个问题我之前也碰到过,SQLAlchemy里直接对布尔字段用func.avg()会报错,因为它没法直接把布尔值当成数值来计算。下面是几种等价于PostgreSQL中::INT类型转换的实现方式:
方法1:使用Column的cast()方法(最简洁)
SQLAlchemy的字段对象本身提供了cast()方法,可以直接将布尔类型转为整数,写法非常直观:
from sqlalchemy import Integer, func from your_module import Table # 替换成你的表模型 # 构建查询 query = session.query( Table.id, func.avg(Table.cond.cast(Integer)).label('avg_cond') ).group_by(Table.id) # 执行查询获取结果 results = query.all()
这里Table.cond.cast(Integer)就等价于PostgreSQL里的cond::INT,把布尔值true转成1,false转成0,之后再求平均就没问题了。
方法2:使用通用的func.cast()函数
如果需要更通用的写法(比如兼容其他数据库),可以用SQLAlchemy的func.cast()函数,效果和上面一样:
from sqlalchemy import Integer, func from your_module import Table query = session.query( Table.id, func.avg(func.cast(Table.cond, Integer)).label('avg_cond') ).group_by(Table.id)
方法3:用case表达式手动映射(最通用,跨数据库)
如果要完全脱离数据库对布尔类型的依赖,还可以用case表达式手动把布尔值映射成1和0,这种写法在任何数据库里都能正常工作:
from sqlalchemy import case, func from your_module import Table query = session.query( Table.id, func.avg( case( [(Table.cond, 1)], else_=0 ) ).label('avg_cond') ).group_by(Table.id)
这个逻辑很直白:当cond为true时取1,否则取0,再对这些数值求平均,结果和前两种方法完全一致。
补充说明
你之前直接用orm_query(Table.id, func.avg(Table.cond))报错的原因是,SQLAlchemy会把布尔字段当成布尔类型处理,而avg()函数需要数值类型的输入,所以必须先完成类型转换或者值映射。
内容的提问来源于stack exchange,提问作者DeanLa
相关产品推荐
相关产品推荐

