gpt4 book ai didi

python - SQLAlchemy 嵌套 CTE 查询

转载 作者:行者123 更新时间:2023-12-03 14:55:12 26 4
gpt4 key购买 nike

sqlalchemy 核心查询构建器似乎取消嵌套并将 CTE 查询重新定位到已编译 sql 的“顶部”。

我正在转换现有的 Postgres 查询,该查询选择深度连接的数据作为单个 JSON 对象。语法非常人为,但它显着减少了大型查询的网络开销。目标是使用 sqlalchemy 核心查询构建器动态构建查询。

这是嵌套 CTE 的最小工作示例

with res_cte as (
select
account_0.name acct_name,
(
with offer_cte as (
select
offer_0.id
from
offer offer_0
where
offer_0.account_id = account_0.id
)
select
array_agg(offer_cte.id)
from
offer_cte
) as offer_arr
from
account account_0
)
select
acct_name::text, offer_arr::text
from res_cte

结果
acct_name,  offer_arr
---------------------
oliver, null
rachel, {3}
buddy, {4,5}

(我的错误使用)核心查询构建器试图取消嵌套 offer_cte并导致每个 offer.id与每个 account_name 相关联结果中。

无需在答案中重新实现这个确切的查询,任何导致类似嵌套 CTE 的示例都是完美的。

最佳答案

我刚刚实现了嵌套 cte 功能。它应该以 1.4.24 版本发布。
拉取请求:https://github.com/sqlalchemy/sqlalchemy/pull/6709

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base

# Model declaration
Base = declarative_base()

class Offer(Base):
__tablename__ = "offer"

id = sa.Column(sa.Integer, primary_key=True)
account_id = sa.Column(sa.Integer, nullable=False)

class Account(Base):
__tablename__ = "account"

id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.TEXT, nullable=False)

# Query construction
account_0 = sa.orm.aliased(Account)

# Watch the nesting keyword set to True
offer_cte = (
sa.select(Offer.id)
.where(Offer.account_id == account_0.id)
.select_from(Offer)
.correlate(account_0).cte("offer_cte", nesting=True)
)
offer_arr = sa.select(sa.func.array_agg(offer_cte.c.id).label("offer_arr"))

res_cte = sa.select(
account_0.name.label("acct_name"),
offer_arr.scalar_subquery().label("offer_arr"),
).cte("res_cte")

final_query = sa.select(
sa.cast(res_cte.c.acct_name, sa.TEXT),
sa.cast(res_cte.c.offer_arr, sa.TEXT),
)
它构造此查询,返回您期望的结果:
WITH res_cte AS 
(
SELECT
account_1.name AS acct_name
, (
WITH offer_cte AS
(
SELECT
offer.id AS id
FROM
offer
WHERE
offer.account_id = account_1.id
)
SELECT
array_agg(offer_cte.id) AS offer_arr
FROM
offer_cte
) AS offer_arr
FROM
account AS account_1
)
SELECT
CAST(res_cte.acct_name AS TEXT) AS acct_name
, CAST(res_cte.offer_arr AS TEXT) AS offer_arr
FROM
res_cte

关于python - SQLAlchemy 嵌套 CTE 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58513337/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com