使用 PostgreSQL/SqlAlchemy 选择 ARRAY 的第一项

DR9*_*913 3 python postgresql sqlalchemy

尝试将我每天运行的一些查询移动到自动脚本中。我在 Postgres 中有一个如下所示:

SELECT regexp_split_to_array(col1, "|")[1] AS item, COUNT(*) AS itemcount FROM Tabel1 GROUP BY item ORDER BY itemcount
Run Code Online (Sandbox Code Playgroud)

在 SqlAlchemy 中,我有这个:

session.query((func.regexp_split_to_array(model.table1.col1, "|")[1]).label("item"), func.count().label("itemcount")).group_by("item").order_by("itemcount")
Run Code Online (Sandbox Code Playgroud)

Python 不能“get_item”,因为它实际上不是一个集合。我已经浏览了文档,似乎无法找到可以让我在不使用 execute 运行原始 SQL 的情况下执行此操作的内容(我可以这样做并且可以工作,但正在寻找下次的解决方案)。

uni*_*rio 5

SQLAlchemy 确实支持使用[...]. 如果您声明的列类型必须为 type postgresql.ARRAY,则它可以工作:

table2 = Table("table2", meta, Column("col1", postgresql.ARRAY(String)))
q = session.query(table2.c.col1[1])
print(q.statement.compile(dialect=postgresql.dialect()))
# SELECT table2.col1[%(col1_1)s] AS anon_1 
# FROM table2
Run Code Online (Sandbox Code Playgroud)

您的代码不起作用的原因是 SQLAlchemy 不知道func.regexp_split_to_array(...)返回一个数组,因为func.foo为了方便起见,它生成了一个通用函数。为了使它工作,我们需要通过指定type_参数来确保 SQLAlchemy 知道函数的返回类型:

q = session.query(func.regexp_split_to_array(table1.c.col1, "|", type_=postgresql.ARRAY(String))[1].label("item"))
print(q.statement.compile(dialect=postgresql.dialect()))
# SELECT (regexp_split_to_array(table1.col1, %(regexp_split_to_array_1)s))[%(regexp_split_to_array_2)s] AS item 
# FROM table1
Run Code Online (Sandbox Code Playgroud)