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

如何将MySQL查询语句转换为Flask-SQLAlchemy实现?

将MySQL分组取最新记录查询转换为Flask-SQLAlchemy实现

需求说明

需要实现对应以下MySQL逻辑的Flask-SQLAlchemy代码:从allflash_dev表中获取每个name对应的最新date记录。原MySQL语句如下:

select t.date, t.name from `capacitydata`.`allflash_dev` t
inner join (
select name, max(date) as MaxDate
    from `capacitydata`.`allflash_dev` group by name)
    tm on t.name = tm.name and t.date = tm.MaxDate;

已定义对应的Flask-SQLAlchemy模型:

# Creating Models
class Block(db.Model):
    __tablename__ = "allflash_dev"
 
    index = db.Column(db.Date, nullable=False, unique=True, primary_key=True)
    date = db.Column(db.Date, nullable=False)
    name = db.Column(db.String(45), nullable=False)
    raw = db.Column(db.String(45), nullable=False)
    free = db.Column(db.String(45), nullable=False)
    frep = db.Column(db.String(45), nullable=False)
    util = db.Column(db.String(45), nullable=False)
    utip = db.Column(db.String(45), nullable=False)

def create_db():
    with app.app_context():
        db.create_all()

# Home route
@app.route("/")
def block():
    details = Block.query.order_by(Block.date.desc())
    return render_template("block.html", details=details)

此前尝试的代码未达到预期效果:

details = db.select([Block.name, db.func.max(Block.date)]).group_by(Block.date, Block.name)

正确实现方法

方法一:子查询关联(对应原MySQL逻辑)

先通过子查询获取每个name的最大date,再关联原表筛选出完整的最新记录:

@app.route("/")
def block():
    # 子查询:获取每个name对应的最大date
    subquery = db.session.query(
        Block.name,
        db.func.max(Block.date).label('max_date')
    ).group_by(Block.name).subquery()
    
    # 关联子查询,过滤出每个name的最新记录
    details = db.session.query(Block).join(
        subquery,
        (Block.name == subquery.c.name) & (Block.date == subquery.c.max_date)
    ).all()
    
    return render_template("block.html", details=details)

方法二:窗口函数(简洁高效)

利用SQL的ROW_NUMBER()窗口函数,按name分组并按date降序排序,直接取每组的第一条记录:

from sqlalchemy import func, over

@app.route("/")
def block():
    # 定义窗口函数:按name分组,date降序生成行号
    row_num = func.row_number().over(
        partition_by=Block.name,
        order_by=Block.date.desc()
    ).label('row_num')
    
    # 子查询添加行号,筛选行号为1的记录
    subquery = db.session.query(Block, row_num).subquery()
    details = db.session.query(subquery).filter(subquery.c.row_num == 1).all()
    
    # 若需直接返回Block对象,可改为:
    # details = db.session.query(Block).from_statement(
    #     db.select(Block).where(row_num == 1)
    # ).all()
    
    return render_template("block.html", details=details)

说明

  • 方法一完全匹配原MySQL的关联逻辑,兼容性强,适用于所有支持分组查询的数据库
  • 方法二使用窗口函数,代码更简洁,执行效率通常更高,适合支持窗口函数的数据库(如MySQL 8.0+、PostgreSQL等)

内容的提问来源于stack exchange,提问作者eduardo stephan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:17:14