在 sqlalchemy 中按 row_number 过滤

Posted

技术标签:

【中文标题】在 sqlalchemy 中按 row_number 过滤【英文标题】:filter by row_number in sqlalchemy 【发布时间】:2016-11-04 17:44:54 【问题描述】:

如何在以下查询中过滤 row_number ==1:

query = session.query(Foo, func.row_number().over(
        partition_by=Foo.foo_field, order_by=desc(Foo.foo_date_time)).label("row_number"))

    query = query.filter(Foo.time_key <= time_key)
    # query = query.filter(row_number == 1)
    result = query.all()

【问题讨论】:

【参考方案1】:

我找到了:

    row_number_column = func.row_number().over(partition_by=Foo.foo_field, order_by=desc(Foo.foo_date_time)).label('row_number')
    query = self.session.query(Foo)
    query = query.filter(Foo.time_key <= time_key)
    query = query.add_column(row_number_column)
    query = query.from_self().filter(row_number_column == 1)

【讨论】:

【参考方案2】:

也可以使用子查询来完成:

sub_query = session.query(
Foo,
func.row_number().over(partition_by=Foo.foo_field, order_by=desc(Foo.foo_date_time)).label("row_number")
)
sub_query = sub_query.filter(Foo.time_key <= time_key).subquery()
query = session.query(sub_query).filter(sub_query.c.row_number == 1)

它基本上生成一个等效的 SQL 语句,就像将 row_number 添加为列一样。

编译语句。

sub_query = session.query(
Foo,
func.row_number().over(partition_by=Foo.foo_field, order_by=desc(Foo.foo_date_time)).label("row_number")
)
sub_query = sub_query.filter(Foo.time_key <= time_key).subquery()
query = session.query(sub_query).filter(sub_query.c.row_number == 1)

str(query.statement.compile())

将生成以下内容:

-- SubQuery function
SELECT anon_1.time_key, 
       anon_1.foo_field, 
       anon_1.foo_date_time, 
       anon_1.row_number 
FROM (
        SELECT  foo.time_key AS time_key,
                foo.foo_field AS foo_field, 
                foo.foo_date_time AS foo_date_time, 
                row_number() OVER (PARTITION BY foo.foo_field ORDER BY foo.foo_date_time DESC) AS row_number 
        FROM foo 
        WHERE foo.time_key <= %(time_key_1)s
    ) AS anon_1 
WHERE anon_1.row_number = %(row_number_1)s

UPDATE:请记住,Query.from_self 方法自 SQLAlchemy 1.4 起已弃用,并将在 2.0 中删除 according to the official documentation

如果有人在使用,可以查看migration guide for this case

【讨论】:

以上是关于在 sqlalchemy 中按 row_number 过滤的主要内容,如果未能解决你的问题,请参考以下文章

在 graphene-sqlalchemy 查询中按 id 过滤

SQLAlchemy如何在多对多中按孩子过滤

如何在 Flask SQLAlchemy 中按多个条件进行过滤?

如何在 Flask-SQLAlchemy 中按 id 删除记录

在 sqlalchemy 中实现窗口函数时需要帮助

使用窗口函数在 Postgres 上使用 SqlAlchemy 限制查询