2013-07-02 17 views
6

Próbuję napisać następujące zapytanie SQL z SQLAlchemy ORM:Złożone zapytania (podzapytania, funkcji okna) z 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; 

To, co zrobiłem do tej pory:

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) 

Jak widać, jest to prawie zamodelowane, ale nie mam pojęcia, jak odwołać się do row_number() wyniku podzapytania z zewnętrznej kwerendy, gdzie. Próbowałem coś takiego jak windowed_contents.c.row_number i dodanie wywołania label() na func okna, ale to nie działa, nie można znaleźć żadnego podobnego przykładu w oficjalnych dokumentach lub w stackoverflow.

Jak można tego dokonać? A może mógłbyś zaproponować lepszy sposób na wykonanie tego zapytania?

Odpowiedz

13

windowed_contents.c.row_number przeciwko label() to jak chcesz to zrobić, pracuje dla mnie (uwaga na sposób select_entity_from() nowego w SQLA 0.8.2 i tu będą potrzebne w 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 (... 'nie działa w wersji 0.5, więc obejście? – dumper

+5

0.5 zostało wypuszczone sześć lat temu, uaktualnienie? w przeciwnym razie tekstowy format, taki jak' text ("ROW NUMBER OVER") 'lub podobny jest prawdopodobnie Twoją najbardziej bezpośrednią drogą. – zzzeek

Powiązane problemy