2013-07-02 28 views
6

Tôi đang cố gắng để viết các truy vấn sql sau đây với SQLAlchemy ORM:truy vấn phức tạp (subqueries, chức năng cửa sổ) với 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; 

Đây là những gì tôi đã thực hiện cho đến nay:

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) 

Như bạn có thể thấy nó được mô hình hóa khá nhiều, nhưng tôi không biết làm thế nào để tham khảo kết quả row_number() của truy vấn phụ từ truy vấn bên ngoài. Tôi đã thử một cái gì đó như windowed_contents.c.row_number và thêm một cuộc gọi label() trên cửa sổ func nhưng nó không hoạt động, không thể tìm thấy bất kỳ ví dụ tương tự nào trong tài liệu chính thức hoặc trong stackoverflow.

Làm cách nào để thực hiện điều này? Và ngoài ra, bạn có thể đề xuất một cách tốt hơn để thực hiện truy vấn này không?

Trả lời

13

windowed_contents.c.row_number chống lại một label() là cách bạn muốn làm điều đó, làm việc cho tôi (lưu ý phương pháp select_entity_from() là mới trong SQLA 0.8.2 và sẽ cần ở đây trong 0,9 vs 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 (... 'không hoạt động trong phiên bản 0.5, do đó, workaround? – dumper

+5

0,5 đã được phát hành sáu năm trước đây. nâng cấp? nếu không một dạng văn bản như' văn bản ("ROW SỐ OVER") 'hoặc tương tự có thể là tuyến đường trực tiếp nhất của bạn. – zzzeek

Các vấn đề liên quan