[英]Sqlalchemy from_self in an inner query referencing outer aliased table
我有这样的sqlalchemy查询:
E = aliased(Entity, name='e')
db.session.query(E) \
.filter(E.user_id == user_id) \
.filter(
db.session.query(Entity) \
.distinct(Entity.original_id) \
.order_by(Entity.original_id, Entity.id.desc())
.filter(Entity.ref_id == E.ref_id) \
.from_self(Entity.flag) \
.order_by(Entity.timestamp.desc()) \
.limit(1).as_scalar()
) \
.order_by(E.timestamp) \
.all()
它产生(大致)以下SQL:
SELECT *
FROM entity AS e
WHERE e.user_id = 1 AND (
SELECT anon_1.entity_flag AS flag
FROM (
SELECT DISTINCT ON (entity.original_id)
entity.flag AS entity_flag, entity.timestamp AS entity_timestamp
FROM entity, entity AS e # THIS "entity AS e" SHOULD NOT BE HERE
WHERE
entity.ref_id = e.ref_id
ORDER BY entity.original_id, entity.id DESC
) AS anon_1
ORDER BY anon_1.entity_timestamp
LIMIT 1
) ORDER BY e.timestamp;
因为它以某种方式将entity AS e
添加到内部查询FROM
子句中,所以它导致WHERE entity.ref_id = e.ref_id
不能按WHERE entity.ref_id = e.ref_id
引用外部表。
为什么将此无关entity AS e
添加到内部FROM
子句中,以及如何克服它?
可能是您发现了Query.from_self()
的局限性:
对于简单的过滤器和排序,自动别名功能仅在有限的方式下起作用。 更雄心勃勃的构造(例如在联接中引用实体)应该更喜欢使用显
Query.subquery()
查询对象,通常使用Query.subquery()
方法来产生显Query.subquery()
查询对象。 始终通过查看SQL来测试查询的结构,以确保特定的结构符合预期!
通常,SQLAlchemy的“自动关联”只考虑FROM对象来进行直接封闭查询的关联,如果需要更深层次的嵌套,则必须使用显式关联。
另一方面,这对您没有帮助。 添加到通话Query.correlate()
通过的边界不破Query.from_self()
由于某种原因,尽管使用它们一起在文档中提到,即使:
在使用
Query.from_self()
或将Query.subquery()
返回的子查询嵌入到另一个select()
构造中时,相关参数会生效。
一种解决方案是使用显式子查询:
In [65]: sq = session.query(Entity.flag, Entity.timestamp).\
...: distinct(Entity.original_id).\
...: order_by(Entity.original_id, Entity.id.desc()).\
...: filter(Entity.ref_id == E.ref_id).\
...: correlate(E).\
...: subquery()
In [66]: q = session.query(E).\
...: filter(E.user_id == 123).\
...: filter(session.query(sq.c.flag).
...: order_by(sq.c.timestamp.desc()).
...: limit(1).
...: as_scalar()).\
...: order_by(E.timestamp)
...:
In [67]: print(q.statement.compile(dialect=postgresql.dialect()))
SELECT e.id, e.ref_id, e.timestamp, e.original_id, e.user_id, e.flag
FROM entity AS e
WHERE e.user_id = %(user_id_1)s AND (SELECT anon_1.flag
FROM (SELECT DISTINCT ON (entity.original_id) entity.flag AS flag, entity.timestamp AS timestamp
FROM entity
WHERE entity.ref_id = e.ref_id ORDER BY entity.original_id, entity.id DESC) AS anon_1 ORDER BY anon_1.timestamp DESC
LIMIT %(param_1)s) ORDER BY e.timestamp
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.