【问题标题】:SQLAlchemy single query to return columns from two tablesSQLAlchemy 单个查询从两个表中返回列
【发布时间】:2021-07-07 00:13:09
【问题描述】:

有没有办法使用一条 SQLAlchemy 查询语句在 Index 表中查找相应的 ID 并从 DimIndexPrice 表中过滤这些行而不使用两条语句?

我觉得我没有通过使用两个语句来使用 SQLAlchemy 的全部表现力。我是 SQL 的初学者,但 union 和 join 在这里没有意义,所以也许这是正确的设计模式。

q = 'VOO'
first_query = db_session.query(Index).filter_by(Symbol=q).first()
second_query = db_session.query(DimIndexPrice).filter_by(IndexID=first_query.ID)

class Index(Base):

    __tablename__ = 'Index'

    ID = Column(Integer, primary_key=True, autoincrement=True)
    Symbol = Column(String(4), unique=True, nullable=False)
    FundName = Column(String(120), unique=True, nullable=False)

    def __init__(self, Symbol, FundName):
        self.Symbol = Symbol
        self.FundName = FundName

    def __repr__(self):
        return '<Index %r>' % (self.Symbol)


class DimIndexPrice(Base):

    __tablename__ = 'DimIndexPrice'

    ID = Column(Integer, primary_key=True, autoincrement=True)
    IndexID = Column(Integer, ForeignKey('Index.ID'), nullable=False)
    Date = Column(Date(), nullable=False)
    Open = Column(Float, nullable=False)
    High = Column(Float, nullable=False)
    Low =Column(Float, nullable=False)
    Close = Column(Float, nullable=False)
    CloseAdjusted = Column(Float, nullable=False)
    Volume = Column(Integer, nullable=False)
    DividendAmount = Column(Float, nullable=False)
    SplitCoefficient = Column(Float, nullable=False)

    def __init__(self,
                 IndexID,
                 Date,
                 Open,
                 High,
                 Low,
                 Close,
                 CloseAdjusted,
                 Volume,
                 DividendAmount,
                 SplitCoefficient):
        self.IndexID = IndexID
        self.Date = Date
        self.Open = Open
        self.High = High
        self.Low = Low
        self.Close = Close
        self.CloseAdjusted = CloseAdjusted
        self.Volume = Volume
        self.DividendAmount = DividendAmount
        self.SplitCoefficient = SplitCoefficient

    def __repr__(self):
        return '<DimIndexPrice %r %s>' % (self.IndexID, self.Date)

【问题讨论】:

  • 这似乎是一个 JOIN 确实是正确的做法
  • @sabik 需要解释一下吗?我需要查询第一个表以获取输入的 ID,然后在第二个表中按此 ID 进行过滤。
  • 是的,这就是 JOIN 的作用
  • 在ID上JOIN两个表,然后在Symbol上过滤
  • 数据库引擎会根据需要自动交换操作顺序以提高效率

标签: python sql sqlalchemy


【解决方案1】:

使用@sabik 的回答和一些反复试验,我得到了我想要的结果。我不确定这是否是最佳实践,或者为什么.filter 可以使用.join.filter_by 不能,或者为什么需要使用== 而不是= 但它有效。请参阅the docs,但它们对我来说很神秘。

combined_query2 = db_session.query(DimIndexPrice).join(Index, DimIndexPrice.IndexID == Index.ID).filter(Index.Symbol==q)

我在下面使用了输出原始 SQL,这有助于故障排除

from sqlalchemy.dialects import sqlite
print(combined_query2.statement.compile(dialect=sqlite.dialect()))

【讨论】:

    【解决方案2】:

    这正是 JOIN 的作用:

    combined_query = Index.query.filter_by(Symbol=q).join(DimIndexPrice)
    

    由于您设置了 ForeignKey,您无需告诉它要加入哪些列;否则,您可以指定:.join(DimIndexPrice, Symbol.c.ID == DimIndexPrice.c.IndexID)

    如果需要,数据库引擎会自动交换操作顺序以提高效率。

    另见this answer

    【讨论】:

    • 阅读文档后,我找到了有关为什么 filter_by 需要放在首位的信息。您的combined_query 中有一个类型,它应该是Index.ID 而不是Symbol.c.IDc 不需要使用。 combined_query[0].__dict__ 仅返回 Index 表的列。由于我正在过滤 Index 表但需要 DimIndexPrice 列,我应该使用联合,对吧?
    • JOIN 合并列; UNION 合并行
    猜你喜欢
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 2019-08-16
    • 2013-12-19
    相关资源
    最近更新 更多