You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将id = ANY(ARRAY(select ...))转换为SQLAlchemy语法?

将SQL的ANY(ARRAY())查询转换为SQLAlchemy代码

问题描述

我有如下简化后的SQL查询:

WITH users as (
   SELECT *
   FROM users
   WHERE created_at >= '2024-01-01'
)
SELECT *
FROM emails
WHERE user_id = ANY(ARRAY(SELECT id FROM users))

由于ANY(ARRAY())能迫使优化器选择更优执行计划,带来显著性能提升,因此我需要使用它而非简单的IN语句。

我尝试了以下SQLAlchemy代码但始终报错:

users_cte = select(User.id, User.name).filter(User.created_at >= date(2024, 01, 01)).cte("user_cte")

select(
   emails.address
)
.filter(Email.user_id.any_(func.array(select(users.cte.id))))

错误信息:

TypeError: ColumnOperators.any_() takes 1 positional argument but 2 were given

请问这种转换在SQLAlchemy中是否可行?

解决方案

完全可行,你的错误源于any_()的使用方式不正确。以下是两种正确的实现方式:

方法一:显式构造ANY(ARRAY(...))

直接用func.any()包裹数组子查询,通过相等判断关联列:

from sqlalchemy import select, func, date
# 假设你的模型类是User和Email
users_cte = select(User.id).filter(User.created_at >= date(2024, 1, 1)).cte("users")

# 生成数组形式的子查询
array_subquery = func.array(select(users_cte.c.id))

# 构造最终查询
query = select(Email.address).filter(Email.user_id == func.any(array_subquery))

方法二:利用SQLAlchemy的any()自动转换

SQLAlchemy的any()方法支持直接传入子查询,底层会根据数据库方言自动生成ANY(ARRAY(...))格式的SQL(以PostgreSQL为例):

from sqlalchemy import select, date
users_cte = select(User.id).filter(User.created_at >= date(2024, 1, 1)).cte("users")

query = select(Email.address).filter(Email.user_id.any(select(users_cte.c.id)))

生成的SQL验证

上述代码执行后,会生成与你需求一致的SQL:

WITH users AS (
    SELECT user.id 
    FROM user 
    WHERE user.created_at >= %(created_at_1)s
)
SELECT email.address 
FROM email 
WHERE email.user_id = ANY(ARRAY(SELECT users.id FROM users))

错误原因解析

你之前的写法Email.user_id.any_(func.array(...))错误,因为any_()是无参数方法,用于标记列需匹配数组元素,正确逻辑是将数组表达式放在==右侧,并用func.any()包裹,或直接给any()传入子查询。

内容的提问来源于stack exchange,提问作者TreeWater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:01:08