SQLAlchemy 单个查询从两个表中返回列
Posted
技术标签:
【中文标题】SQLAlchemy 单个查询从两个表中返回列【英文标题】:SQLAlchemy single query to return columns from two tables 【发布时间】: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上过滤 数据库引擎会根据需要自动交换操作顺序以提高效率 【参考方案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.ID
。 c
不需要使用。 combined_query[0].__dict__
仅返回 Index
表的列。由于我正在过滤 Index
表但需要 DimIndexPrice
列,我应该使用联合,对吧?
JOIN 合并列; UNION 合并行以上是关于SQLAlchemy 单个查询从两个表中返回列的主要内容,如果未能解决你的问题,请参考以下文章
在一个查询Access数据库中从具有不同字段的两个不同表中选择列