Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment convertir une sous-requête scalaire SQL en expression SQLAlchemy

Utilisez 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)

Utilisation de as_scalar() limite les colonnes et les lignes renvoyées à 1, de sorte que vous ne pouvez pas obtenir l'intégralité de l'objet de modèle en l'utilisant (comme query(PropertyValuation) est une sélection de tous les attributs de PropertyValuation ), mais en obtenant juste la évaluation l'attribut fonctionne.

Il n'est pas nécessaire de le passer plus tard. Votre façon actuelle de déclarer la sous-requête est correcte, car SQLAlchemy peut corrèlent automatiquement les objets FROM avec ceux d'une requête englobante . J'ai essayé de créer des modèles qui représentent en quelque sorte ce que vous avez, et voici comment fonctionne la requête ci-dessus (avec des sauts de ligne et une indentation supplémentaires pour la lisibilité) :

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