【问题标题】:Using window functions to LIMIT a query with SqlAlchemy on Postgres使用窗口函数在 Postgres 上使用 SqlAlchemy 限制查询
【发布时间】:2013-07-02 23:14:39
【问题描述】:

我正在尝试使用 sqlalchemy ORM 编写以下 sql 查询:

SELECT * FROM
   (SELECT *, row_number() OVER(w)
    FROM (select distinct on (grandma_id, author_id) * from contents) as c
    WINDOW w AS (PARTITION BY grandma_id ORDER BY RANDOM())) AS v1
WHERE row_number <= 4;

这是我到目前为止所做的:

s = Session()

unique_users_contents = (s.query(Content).distinct(Content.grandma_id,
                                                  Content.author_id)
                         .subquery())

windowed_contents = (s.query(Content,
                             func.row_number()
                             .over(partition_by=Content.grandma_id,
                                   order_by=func.random()))
                     .select_from(unique_users_contents)).subquery()

contents = (s.query(Content).select_from(windowed_contents)
            .filter(row_number >= 4)) ##  how can I reference the row_number() value?

result = contents
for content in result:
    print "%s\t%s\t%s" % (content.id, content.grandma_id,
                          content.author_id)

如您所见,它几乎是建模的,但我不知道如何从外部查询 where 引用子查询的 row_number() 结果。我尝试了类似windowed_contents.c.row_number 并在窗口函数上添加label() 调用,但它不起作用,在官方文档或stackoverflow 中找不到任何类似的示例。

如何做到这一点?另外,您能否建议一种更好的方法来进行此查询?

【问题讨论】:

    标签: python sql sqlalchemy


    【解决方案1】:

    windowed_contents.c.row_numberlabel() 是你的做法,对我有用(注意 select_entity_from() 方法是 SQLA 0.8.2 中的新方法,在 0.9 与 select_from() 中需要):

    from sqlalchemy import *
    from sqlalchemy.orm import *
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    class Content(Base):
        __tablename__ = 'contents'
    
        grandma_id = Column(Integer, primary_key=True)
        author_id = Column(Integer, primary_key=True)
    
    
    s = Session()
    
    unique_users_contents = s.query(Content).distinct(
                                Content.grandma_id, Content.author_id).\
                                subquery('c')
    
    q = s.query(
            Content,
            func.row_number().over(
                    partition_by=Content.grandma_id,
                    order_by=func.random()).label("row_number")
        ).select_entity_from(unique_users_contents).subquery()
    
    q = s.query(Content).select_entity_from(q).filter(q.c.row_number <= 4)
    
    print q
    

    【讨论】:

    • func.row_number().over(... 在 0.5 版本中不起作用,所以解决方法?
    • 0.5 于六年前发布。升级?否则,text("ROW NUMBER OVER") 或类似的文本形式可能是您最直接的途径。
    猜你喜欢
    • 2018-12-23
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 2021-12-09
    相关资源
    最近更新 更多