SQLAlchemy:hybrid_property表达式和子查询

Oli*_*ign 5 python sqlalchemy

我正在尝试使用SQLAlchemy做一个复杂的hybrid_property:我的模型是

class Consultation(Table):
    patient_id = Column(Integer)
    patient = relationship('Patient', backref=backref('consultations', lazy='dynamic'))

class Exam(Table):
    consultation_id = Column(Integer)
    consultation = relationship('Consultation', backref=backref('exams', lazy='dynamic'))

class VitalSign(Table):
    exam_id = Column(Integer)
    exam = relationship('Exam', backref=backref('vital', lazy='dynamic'))
    vital_type = Column(String)
    value = Column(String)

class Patient(Table):
    patient_data = Column(String)

    @hybrid_property
    def last_consultation_validity(self):
        last_consultation = self.consultations.order_by(Consultation.created_at.desc()).first()
        if last_consultation:
            last_consultation_conclusions = last_consultation.exams.filter_by(exam_type='conclusions').first()
            if last_consultation_conclusions:
                last_consultation_validity = last_consultation_conclusions.vital_signs.filter_by(sign_type='validity_date').first()
                if last_consultation_validity:
                    return last_consultation_validity

        return None

    @last_consultation_validity.expression
    def last_consultation_validity(cls):
        subquery = select([Consultation.id.label('last_consultation_id')]).\
            where(Consultation.patient_id == cls.id).\
            order_by(Consultation.created_at.desc()).limit(1)
        j = join(VitalSign, Exam).join(Consultation)
        return select([VitalSign.value]).select_from(j).select_from(subquery).\
            where(and_(Consultation.id == subquery.c.last_consultation_id, VitalSign.sign_type == 'validity_date'))
Run Code Online (Sandbox Code Playgroud)

如您所见,我的模型非常复杂。患者得到咨询。考试和VitalSigns是咨询的级联数据。这样的想法是,所有协商都不会获得有效性,但是新的协商会使先前的协商有效性变得不那么有趣。如果患者在先前的咨询中仍然有效,我将不感兴趣。

我想做的是能够通过hybrid_property last_consultation_validity进行订购。

输出SQL对我来说看起来不错:

SELECT vital_sign.value 
FROM (SELECT consultation.id AS last_consultation_id 
FROM consultation, patient 
WHERE consultation.patient_id = patient.id ORDER BY consultation.created_at DESC
LIMIT ? OFFSET ?), vital_sign JOIN exam ON exam.id = vital_sign.exam_id JOIN consultation ON consultation.id = exam.consultation_id 
WHERE consultation.id = last_consultation_id AND vital_sign.sign_type = ?
Run Code Online (Sandbox Code Playgroud)

但是,当我通过last_consultation_validity对患者进行排序时,这些行不会得到排序...当我在hybrid_property外部执行相同的选择时,为每个患者检索日期(只需设置Patient.id),就可以得到很好的值。令人惊讶的是,SQL稍有不同,patient在FROM中删除了SELECT。

因此,我实际上想知道这是否是SQLAlchemy中的错误或我做错了什么...任何帮助将不胜感激。