2017-11-24 2 views
0

Hier ist eine Postgres-Abfrage, die Ich mag würde übersetzen ORM sqlalchemy:SQLAlchemy: Brauchen Sie Hilfe diese komplexe rohe Abfrage ORM zu übersetzen (Subqueries, Fensterfunktionen)

SELECT 
    * 
FROM 
    (
    SELECT 
     *, 
     date_trunc(
     'hour', 
     time_obs + INTERVAL '15' MINUTE 
    ) AS usedTimestamp, 
     ROW_NUMBER() OVER(
     PARTITION BY icao, 
     date_trunc(
      'hour', 
      time_obs + INTERVAL '15' MINUTE 
     ) 
     ORDER BY 
     LEAST(
      EXTRACT(
      MINUTE 
      FROM 
       time_obs 
     ), 
      60 - EXTRACT(
      MINUTE 
      FROM 
       time_obs 
     ) 
     ) 
    ) AS seqnum 
    FROM 
     metar_current 
    WHERE 
     icao = 'DGAA' 
) AS dt 
WHERE 
    seqnum = 1 
AND LEAST(
    ` EXTRACT(
    MINUTE 
    FROM 
     time_obs 
), 
    60 - EXTRACT(
    MINUTE 
    FROM 
     time_obs 
) 
) <= 15 
ORDER BY 
    time_obs ASC 

Wenn es nicht möglich ist (oder zu schwierig), dies in sqlalchemy ORM zu übersetzen, gibt es dann eine Möglichkeit, dass ich das als rohe SQL abfragen könnte, aber referenziere die resultierenden Daten mit Spaltennamen?

+1

Zum "könnte [ich] dies als rohe sql abfragen": ['Query.from_statement()'] (http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm .query.Query.from_statement) ermöglicht es Ihnen, Abfragen für SQL-Anweisungen auszuführen, die ORM-Entitäten zurückgeben. –

Antwort

0

Es dauerte eine Weile, aber ich konnte es selbst herausfinden - obwohl ich nicht sicher bin, dass dies der optimale Weg ist.

seqnum = func.row_number().over(
    partition_by=[Metar.icao, 
        func.date_trunc('hour', Metar.time_obs + text("INTERVAL '15' MINUTE")) 
        ], 
    order_by=func.least(func.extract("MINUTE", Metar.time_obs), 
         60 - func.extract("MINUTE", Metar.time_obs))).label('seqnum') 

dt = session.query(Metar, 
        func.date_trunc('hour', Metar.time_obs + text("INTERVAL '15' MINUTE")).label('usedTimestamp'), 
        seqnum 
        ).filter(Metar.icao == icao).subquery('dt') 

q = session.query(Metar, dt.c.usedTimestamp).filter(dt.c.seqnum == 1, 
                dt.c.icao == Metar.icao, 
                dt.c.time_obs == Metar.time_obs, 
                func.least(func.extract("MINUTE", Metar.time_obs), 
                   60 - func.extract("MINUTE", Metar.time_obs)) < 15) \ 
    .order_by(Metar.time_obs).all() 

Der Grund, dass ich Metar von dt wie in der Original-Raw-Abfrage, anstatt nur die Auswahl an dt verbunden war, so dass ich die resultierenden Daten von Metar Klasse Eigenschaften s‘zugreifen.

Verwandte Themen