python - SQLAlchemy 未在正确选择时构建 JOIN
问题描述
我正在尝试将以下查询转换为 SQLAlchemy ORM 查询:
SELECT applications.*,
appversions.version
FROM applications
JOIN appversions
ON appversions.id = (SELECT id
FROM appversions
WHERE appversions.app_id = applications.id
ORDER BY sort_ver DESC
LIMIT 1)
表的模型如下:
Base = declarative_base()
class Application(Base):
__tablename__ = 'applications'
id = Column(Integer, primary_key = True)
group = Column(Unicode(128))
artifact = Column(Unicode(128))
versions = relationship("AppVersion", backref = "application")
class AppVersion(Base):
__tablename__ = 'versions'
id = Column(Integer, primary_key = True)
app_id = Column(Integer, ForeignKey('applications.id'))
version = Column(Unicode(64))
sort_ver = Column(Unicode(64))
到目前为止,我提出的查询是:
subquery = select([AppVersion.id]). \
where(AppVersion.app_id == Application.id). \
order_by(AppVersion.sort_ver). \
limit(1). \
alias()
query = session.query(Application). \
join(AppVersion, AppVersion.id == subquery.c.id) \
.all()
但是,这会产生以下 SQL 语句和错误:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: anon_1.id
[SQL: SELECT applications.id AS applications_id, applications."group" AS applications_group, applications.artifact AS applications_artifact
FROM applications JOIN versions ON versions.id = anon_1.id]
我尝试了各种不同的方法来生成子查询并尝试“附加”子 SELECT 命令,但没有任何积极影响。
有没有办法强制 SQLAlchemy 查询生成器正确附加子 SELECT?
解决方案
感谢@Ilja Everilä 在正确方向上的推动,生成正确查询的代码是:
subquery = select([AppVersion.id]). \
where(AppVersion.app_id == Application.id). \
order_by(AppVersion.sort_ver). \
limit(1). \
correlate(Application)
query = session.query(Application). \
join(AppVersion, AppVersion.id == subquery) \
.all()
主要的变化是使用了correlate()方法,它改变了 SQLAlchemy 构造子查询的方式。
要解释为什么会这样,需要对 SQL 子查询的分类和处理方式有所了解。我发现的最佳解释来自 https://www.geeksforgeeks.org/sql-correlated-subqueries/:
对于普通的嵌套子查询,内部 SELECT 查询首先运行并执行一次,返回主查询使用的值。但是,相关子查询对外部查询考虑的每个候选行执行一次。换句话说,内部查询由外部查询驱动。
推荐阅读
- javascript - 如何在 puppeteer-cluster 中使用 puppeteer.connect()?
- c++ - 需要帮助比较开关盒以确保选择的卡片不相同
- python - 在同一脚本中创建和激活 Conda 环境
- python - 如何在 tkinter 中更新由 matplotlib 创建的图形
- algorithm - 目标未知时的搜索算法
- r - 使用 mutate_at 使用数据框中的多个其他列创建新列
- android - 在 Android 应用中过滤掉 Facebook Audience Network 中不适合儿童的广告
- jquery - 追加时(基本上是在某些东西出现之后。)
- uproot - 从 .root 文件中读取一棵树,然后制作零填充的 .h5 文件
- python - 我正在尝试使用漂亮的汤访问python中每个标题标签内的每个类标签内的内容