SQLAlchemy:从子查询返回 ORM 对象

SQLAlchemy: return ORM objects from subquery

提问人:AivanF. 提问时间:11/17/2023 最后编辑:AivanF. 更新时间:11/17/2023 访问量:29

问:

我需要联接几个表,然后根据模型 C.id 分区的某个规则返回不同的行(为简单起见,让我们使用)。由于它是一个窗口函数,所以不能直接在 中使用,所以需要一个外部查询来过滤。它有效,但它将移动模型变成了一个子查询,Alchemy 现在返回原始行,而不是 GPT 建议使用的模型对象,但它们似乎添加了重复提取,完整的笛卡尔乘积打破了逻辑,而不是对已经可用的列进行简单的解析。我怎样才能实现它?row_number()==1where:(with_entitiesadd_entityfrom

# Main query
subq = db.query(ModelA, ModelB, ModelC)
subq = subq.filter(ModelA.some_tag == ModelB.some_tag)
subq = subq.filter(ModelA.some_tag == ModelC.some_tag)
subq = subq.filter(ModelA.some_tag == "31415926535")  # just to simplify testing

# Additional field by a window function
partition_col = func.row_number().over(partition_by=ModelC.id).label("partition_col_name")
subq = subq.add_column(partition_col)

# Outer query
subq = subq.subquery()
q = db.query(subq).filter(subq.c["partition_col_name"] == 1)

尝试添加额外的包装以获取对象...但是为什么我会得到错误的结果??SQL of 是完全正确的,并在 psql 中返回 2 行,但 Alchemy 只看到第 1 行finalqo_0

from sqlalchemy import text, func
from psycopg2.extensions import adapt as sqlescape
from database import get_db, ModelA, ModelB, ModelC
db = next(get_db())

# Main query
subq = db.query(ModelA, ModelB, ModelC)
subq = subq.filter(ModelA.some_tag == ModelB.some_tag)
subq = subq.filter(ModelA.some_tag == ModelC.some_tag)
subq = subq.filter(ModelA.some_tag == "31415926535")  # just to simplify testing

# Additional field by a window function
partition_col = func.row_number().over(partition_by=ModelC.id).label("partition_col_name")
subq = subq.add_column(partition_col)
subq = subq.subquery()

# Outer query
outerq = db.query(subq).filter(subq.c["partition_col_name"] == 1)
# outerq = outerq.limit(128)

# Final query for ORM
compiledq = outerq.statement.compile(dialect=db.bind.dialect)
params = {k: sqlescape(v) for k, v in compiledq.params.items()}
finalq = db.query(ModelA, ModelB, ModelC).from_statement(text(str(compiledq) % params))

print(len(outerq.all()))  # 2
print(len(finalq.all()))  # 1 ?!

更新

这种方式更简单,效果很好:

finalq = db.query(ModelA, ModelB, ModelC).from_statement(outerq)

但我仍然想知道为什么以前的自定义查询编译方法不起作用 🤔

python sqlalchemy orm 窗口函数

评论


答:

0赞 snakecharmerb 11/17/2023 #1

为此,可以将查询置于from_statement调用中,该调用是从查询模型的查询中调用的:

qq = db.query(ModelA, ModelB, ModelC).from_statement(q)