sql >> Base de Datos >  >> RDS >> Mysql

Cómo convertir una subconsulta escalar SQL a una expresión SQLAlchemy

Use 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 las columnas y filas devueltas a 1, por lo que no puede usar todo el objeto del modelo (como query(PropertyValuation) es una selección de todos los atributos de PropertyValuation ), pero obteniendo solo la valoración el atributo funciona.

No hay necesidad de pasarlo más tarde. Su forma actual de declarar la subconsulta está bien tal como está, ya que SQLAlchemy puede correlacionar automáticamente los objetos FROM con los de una consulta adjunta . Intenté crear modelos que representaran algo lo que tienes, y así es como funciona la consulta anterior (con saltos de línea agregados y sangría para facilitar la lectura):

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