[英]Filter query by linked object key in SQLAlchemy
从标题来看, 这将是完全相同的问题,但是我看不到任何答案如何适用于我的用例:
我有两个班级,并且他们之间有关系:
treatment_association = Table('tr_association', Base.metadata,
Column('chronic_treatments_id', Integer, ForeignKey('chronic_treatments.code')),
Column('animals_id', Integer, ForeignKey('animals.id'))
)
class ChronicTreatment(Base):
__tablename__ = "chronic_treatments"
code = Column(String, primary_key=True)
class Animal(Base):
__tablename__ = "animals"
treatment = relationship("ChronicTreatment", secondary=treatment_association, backref="animals")
我希望只能选择经过代码“ X”处理的动物。 我尝试了很多方法。
这个失败,并带有AttributeError
:
sql_query = session.query(Animal.treatment).filter(Animal.treatment.code == "chrFlu")
for item in sql_query:
pass
mystring = str(session.query(Animal))
这很高兴地返回了未过滤动物的列表:
sql_query = session.query(Animal.treatment).filter(ChronicTreatment.code == "chrFlu")
for item in sql_query:
pass
mystring = str(session.query(Animal))
我可以将上述线程中与示例最接近的东西放在一起:
subq = session.query(Animal.id).subquery()
sql_query = session.query(ChronicTreatment).join((subq, subq.c.treatment_id=="chrFlu"))
for item in sql_query:
pass
mystring = str(session.query(Animal))
mydf = pd.read_sql_query(mystring,engine)
也失败,并出现AttributeError
。
您能帮我对这个列表进行排序吗?
首先,表定义存在两个问题:
1)在treatment_association
你有Integer
列指向chronic_treatments.code
而code
为String
列。
我认为最好在chronic_treatments
使用一个整数id
,这样您就不必在另一个表中重复该字符串代码,并且以后也有机会将更多字段添加到chronic_treatments中。 更新:并不完全正确,您仍然可以添加更多字段,但是如果您决定重命名,则更改“代码”会更加复杂。
2)在Animal
模型中,您有一个名为treatment
的关系。 这是令人困惑,因为你有很多一对多的关系,应该是复数- treatments
。
修复以上两个问题之后,应该更清楚为什么您的查询不起作用。 这个(我用treatment
代替treatments
:
sql_query = session.query(Animal.treatments).filter(
Animal.treatments.code == "chrFlu")
Animal.treatments
表示多对多关系,它不是SQL Alchemy模式,因此您不能将其传递给query
也不能在filter
使用。
下一个由于相同的原因而无法工作(您将Animal.treatments
传递到query
。
最后一个更接近,您实际上需要join
才能获得结果。
我认为将查询理解为SQL更容易了(无论如何,您都需要了解SQL才能使用sqlalchemy):
animals = session.query(Animal).from_statement(text(
"""
select distinct animals.* from animals
left join tr_association assoc on assoc.animals_id = animals.id
left join chronic_treatments on chronic_treatments.id = assoc.chronic_treatments_id
where chronic_treatments.code = :code
""")
).params(code='chrFlu')
它将选择animals
并通过tr_association
加入chronic_treatments
tr_association
并通过代码过滤结果。
有了这个,很容易使用无SQL语法重写它:
sql_query = session.query(Animal).join(Animal.treatments).filter(
ChronicTreatment.code == "chrFlu")
这将返回您想要的-用给定代码进行了相关慢性治疗的动物列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.