使用sqlalchemy的复杂查询(子查询,窗口函数)

gon*_*onz 11 python sql sqlalchemy

我正在尝试使用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;
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,它几乎是建模的,但我不知道如何row_number()从外部查询中引用子查询的结果.我尝试了类似的东西windowed_contents.c.row_number,并label()在窗口函数上添加了一个调用,但它无法正常工作,在官方文档或stackoverflow中找不到任何类似的示例.

如何实现这一目标?而且,你能建议一个更好的方法来做这个查询吗?

zzz*_*eek 21

windowed_contents.c.row_number反对a label()是你怎么做的,对我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
Run Code Online (Sandbox Code Playgroud)

  • 0.5六年前发布了.升级?否则,文本形式如"文本"("ROW NUMBER OVER")或类似文件可能是您最直接的途径. (7认同)