2013-07-02 60 views
6

我试着写与SQLAlchemy的ORM下面的SQL查询:复杂的查询(子查询,窗口功能)与SQLAlchemy的

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) 

正如你所看到的,它的建模非常多,但我不知道如何从外部查询中引用row_number()子查询的结果。我尝试了一些类似于windowed_contents.c.row_number并在窗口func中添加label()调用,但它不起作用,在官方文档或计算器中找不到任何类似的示例。

这是如何实现的?另外,你能否提出一个更好的方法来做这个查询?

回答

13

windowed_contents.c.row_number针对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 
+0

' func.row_number()。over(...'在0.5版本中不起作用,所以解决方法? – dumper

+5

0.5是在六年前发布的,升级?否则为文本格式,例如text(“ROW NUMBER OVER”)或类似可能是你最直接的路线。 – zzzeek