这是我的查询的简化版本:
subquery = (select(['latitude'])
.select_from(func.unnest(func.array_agg(Room.latitude))
.alias('latitude')).limit(1).as_scalar())
Room.query.with_entities(Room.building, subquery).group_by(Room.building).all()
执行它时,我在SQLAlchemy内部得到一个错误:
File ".../sqlalchemy/sql/selectable.py", line 429, in columns
self._populate_column_collection()
File ".../sqlalchemy/sql/selectable.py", line 992, in _populate_column_collection
for col in self.element.columns._all_columns:
AttributeError: 'list' object has no attribute '_all_columns'
在调试器中检查它会向我显示:
>>> self.element
<sqlalchemy.sql.functions.Function at 0x7f72d4fcae50; unnest>
>>> str(self.element)
'unnest(array_agg(rooms.id))'
>>> self.element.columns
[<sqlalchemy.sql.functions.Function at 0x7f72d4fcae50; unnest>]
问题始于SQLAlchemy 0.9.4;在0.9.3中一切正常。
在SQLAlchemy 0.9.3中运行时,执行以下查询(按预期方式):
SELECT rooms.building AS rooms_building,
(SELECT latitude
FROM unnest(array_agg(rooms.latitude)) AS latitude
LIMIT 1) AS anon_1
FROM rooms
GROUP BY rooms.building
我在这里做错了还是SQLAlchemy中的错误?
答案 0 :(得分:0)
这是SQLAlchemy中的一个错误:https://bitbucket.org/zzzeek/sqlalchemy/issue/3137/decide-what-funcxyz-alias-should-do
func.foo().alias()
实际上应该等同于func.foo().select().alias()
,但是在这种情况下,这将推出您不想要的第二级嵌套。所以要对API进行修正可能需要1.0,除非我现在可以确定func.foo().alias()
完全无法使用。
根据SQLAlchemy开发人员的说法,正确的方法是:
subquery = (select(['*']).select_from(
func.unnest(func.array_agg(Room.latitude)))
.limit(1)
.as_scalar())
很可能下一个版本(我假设为0.9.8)将恢复旧的行为:
我正在恢复旧的行为,但现在只使用
select(['*'])
。该列未命名。 PG根据FROM中的别名分配列名的行为有点神奇(例如,如果函数返回多个列,那么它会忽略该名称并使用函数报告的名称?)