Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como converter subconsulta escalar SQL para expressão SQLAlchemy


Use as_scalar() , ou 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 as colunas e linhas retornadas a 1, então você não pode obter o objeto de modelo inteiro usando-o (como query(PropertyValuation) é uma seleção de todos os atributos de PropertyValuation ), mas obtendo apenas a avaliação atributo funciona.

Não há necessidade de passar depois. Sua maneira atual de declarar a subconsulta está correta, pois SQLAlchemy pode correlacionar automaticamente os objetos FROM aos de uma consulta delimitadora . Eu tentei criar modelos que representam um pouco o que você tem, e aqui está como a consulta acima funciona (com quebras de linha e recuo adicionados para facilitar a leitura):
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