在SQLAlchemy中按链接对象键过滤查询

时间:2016-02-04 18:37:11

标签: python sqlite pandas sqlalchemy

根据标题this判断是完全相同的问题,但我无法看到任何答案如何适用于我的用例:

我有两个班级和他们之间的关系:

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 个答案:

答案 0 :(得分:1)

首先,表定义存在两个问题:

1)treatment_association Integerchronic_treatments.code列指向codeStringid列。

我认为在chronic_treatments中有一个整数Animal会更好,所以你不要在另一个表中复制字符串代码并且还有机会添加稍后会有更多领域到chronic_treatments。 更新:不完全正确,您仍然可以添加更多字段,但更改您的代码会变得更加复杂。如果你决定重命名它。

2)在treatment模型中,您有一个名为treatments的关系。这很令人困惑,因为你有多对多的关系,它应该是复数 - treatment

修正上述两项后,应该更清楚为什么你的查询不起作用。 这一个(我将treatments替换为sql_query = session.query(Animal.treatments).filter( Animal.treatments.code == "chrFlu")

Animal.treatments

query表示多对多关系,它不是SQL Alchemy模式,因此您无法将其传递给filter,也无法在Animal.treatments中使用}。

下一个因为同样的原因无法工作(您将query传递到join

最后一个更接近,您实际上需要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') 才能获得结果。

我认为将查询理解为SQL更容易(无论如何你需要知道SQL能够使用sqlalchemy):

animals

它会选择chronic_treatments并通过tr_association加入sql_query = session.query(Animal).join(Animal.treatments).filter( ChronicTreatment.code == "chrFlu") 并按代码过滤结果。

有了这个,很容易使用无SQL语法重写它:

   <Style TargetType="TextBox" >
                        <Setter Property="OverridesDefaultStyle" Value="false"/>
                        <Setter Property="VerticalAlignment" Value="Center"/>
                        <Setter Property="HorizontalAlignment" Value="Left"/>
                        <Setter Property="Margin" Value="5,3" />
                        <Style.Triggers>
                            <Trigger Property="Validation.HasError" Value="True">
                                <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>

这将返回你想要的东西 - 一份与给定代码有相关长期治疗的动物清单。