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