我试图通过sqlalchemy在postgres中编写一个函数来计算嵌套json值的平均值。我要平均的值在统计信息表中,带有一个scores列,该列包含这样的json字典(过滤到相关结构):{1:{'score':0.0},2:{'score' :0.0} ...}。
用postgres编写,查询如下:
SELECT *, avg((v->>'score')::float) AS average_score
FROM lms.statistics, jsonb_each(statistics.scores) js(k, v)
WHERE jsonb_typeof(scores) != 'null'
GROUP BY statistics.id
我主要将其转换为以下sqlalchemy代码:
(
session.query(Statistics)
.add_columns(literal_column("avg((v->>'score')::float)").label('average_score'))
.filter(literal("jsonb_typeof(statistics.scores != 'null'"))
.group_by(Statistics.id)
).all()
但是,无论我做什么,sqlalchemy都不允许我包含此查询所依赖的jsonb_each。我什至尝试重组查询以使用显式联接,而sqlalchemy的.join将不接受literal_column,文本或任何带有外部联接或指定伪联接条件的欺骗手段。当必须要使用sqlalchemy标准以将纯文本查询插入FROM或JOIN语句时,我尽力尝试这样做。
答案 0 :(得分:2)
使用返回标量或一组单列的函数,您只需使用func.something.alias('x')
和column('x')
。不幸的是,SQLAlchemy不支持显式地对列进行别名,因此处理返回多列组合的函数有些棘手。如果是jsonb_each
the default names are key
and value
,那么您可以使用以下内容:
v = column('value', type_=JSONB)
score = v['score'].astext.cast(Float)
session.query(Statistics,
func.avg(score).label('average_score')).\
select_from(Statistics,
func.jsonb_each(Statistics.scores).alias()).\
filter(func.jsonb_typeof(Statistics.scores) != 'null').\
group_by(Statistics.id)