Mysql
 sql >> Database >  >> RDS >> Mysql

Come convertire una sottoquery scalare SQL in un'espressione SQLAlchemy

Usa as_scalar() o label() :

subquery = (
    session.query(PropertyValuation.valuation)
    .filter(PropertyValuation.zip_code == Property.address_zip)
    .order_by(func.abs(func.datediff(PropertyValuation.as_of, Sale.date_sold)))
    .limit(1)
)

query = session.query(Sale.agent_id,
                      Sale.property_id,
                      Property.address_zip,
                      # `subquery.as_scalar()` or
                      subquery.label('back_valuation'))\
        .join(Property)

Usando as_scalar() limita le colonne e le righe restituite a 1, quindi non puoi ottenere l'intero oggetto del modello utilizzandolo (come query(PropertyValuation) è una selezione di tutti gli attributi di PropertyValuation ), ma ottenendo solo la valutazione l'attributo funziona.

Non c'è bisogno di passarlo più tardi. Il tuo attuale modo di dichiarare la sottoquery va bene così com'è, poiché SQLAlchemy può correlano automaticamente gli oggetti FROM a quelli di una query di inclusione . Ho provato a creare modelli che rappresentano in qualche modo ciò che hai, ed ecco come funziona la query sopra (con interruzioni di riga e indentazione aggiunte per la leggibilità):

In [10]: print(query)
SELECT sale.agent_id AS sale_agent_id,
       sale.property_id AS sale_property_id,
       property.address_zip AS property_address_zip,
       (SELECT property_valuations.valuation
        FROM property_valuations 
        WHERE property_valuations.zip_code = property.address_zip
        ORDER BY abs(datediff(property_valuations.as_of, sale.date_sold))
        LIMIT ? OFFSET ?) AS back_valuation 
FROM sale
JOIN property ON property.id = sale.property_id