Flask SQLAlchemy 中所有组的第一行

First row of all groups in Flask SQLAlchemy

我想按 gauge_id 对数据库进行分组,然后获取具有最大值 time_col 的行。这是我当前的代码:

rain_gauge_datas = db.session.query(DataEntry.gauge_id, func.max(DataEntry.time_col)).group_by(DataEntry.gauge_id).all()

但我只能同时获得gauge_idtime_col。当我添加另一列(阅读)时,如下所示:

rain_gauge_datas = db.session.query(DataEntry.gauge_id, DataEntry.reading, func.max(DataEntry.time_col)).group_by(DataEntry.gauge_id).all()

它给出了这个错误。

column "data_entry.reading" must appear in the GROUP BY clause or be used in an aggregate function

如何return每个组的顶行?提前致谢。

一种方法是使用 common table expression (CTE)。 CTE 通过结果集创建组的虚拟 table,然后我们可以加入。

SQL 会是

with cte as (
    select gauge_id, max(time_col) as max_time
    from data_entries
    group by gauge_id
)

select d.* from data_entries d
join cte 
on d.gauge_id = cte.gauge_id 
and d.time_col = cte.max_time;

SQL炼金术相当于

cte = (session.query(DataEntry.gauge_id, sa.func.max(DataEntry.time_col).label('max_time'))
              .group_by(DataEntry.gauge_id)
              .cte(name='cte'))
query = session.query(DataEntry).join(cte, sa.and_(
    DataEntry.gauge_id == cte.c.gauge_id,
    DataEntry.time_col == cte.c.max_time
))

(上面的示例使用“纯”SQLAlchemy 而不是 Flask-SQLAlchemy - 用 db. 和 [= 替换 sa. 应该足够了14=] 和 db.session 让它在 Flask_SQLAlchemy)

中工作

值得注意的是,直到 v12,CTE 才在 Postgresql 中得到有效处理,因此如果您使用的是早期版本,最好将 CTE 内联为子查询。