Skip to main content
 首页 » 编程设计

python之重新排列 SQLAlchemy Select 对象中的列

2025年05月04日13bonelee

问题

如何重新排序 SQLAlchemy 查询对象中的列?

例子

给定一个表示以下查询的 SQLAlchemy 核心 Select 对象:

>>> print s 
SELECT sum(accounts.amount) AS amount_sum, accounts.name  
FROM accounts GROUP BY accounts.name 
 LIMIT :param_1 

我想形成一个具有完全相同结构的 Select 对象,但列的顺序移动了

SELECT accounts.name,  sum(accounts.amount) AS amount_sum 
FROM accounts GROUP BY accounts.name 
 LIMIT :param_1 

我试过的没用

我想在不显着扩展 SQL 的情况下执行此操作。我已经尝试使用 with with_only_columns 并且它嵌套了查询,同样,我想避免这种情况

>>> print s.with_only_columns(list(s.columns)[::-1]) 
SELECT name, amount_sum  
FROM (SELECT sum(accounts.amount) AS amount_sum, accounts.name AS name  
FROM accounts GROUP BY accounts.name 
 LIMIT :param_1) GROUP BY accounts.name 
 LIMIT :param_2 

编辑

需要说明的是,上面的例子只是一个例子。我正在寻找一个通用的解决方案来对任意查询执行此操作。理想情况下,该函数将使用 Select 对象和按正确顺序排列的列名列表。

编辑2

创建s的代码。同样,我正在寻找一般问题的解决方案,而不仅仅是一个明确修复以下顺序的代码片段。

import sqlalchemy 
 
metadata = sqlalchemy.MetaData() 
 
t = sqlalchemy.Table('accounts', metadata, 
             sqlalchemy.Column('name', sqlalchemy.String), 
             sqlalchemy.Column('amount', sqlalchemy.Integer), 
             sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True), 
             ) 
 
s = (sqlalchemy.select([sqlalchemy.sql.functions.sum(t.c.amount).label('sum'),     
                         t.c.name]) 
        .group_by(t.c.name) 
        .limit(10)) 
 
print s 
 
 
SELECT sum(accounts.amount) AS sum, accounts.name  
FROM accounts GROUP BY accounts.name 
 LIMIT :param_1 

请您参考如下方法:

您使用 with_only_columns 但您放入其中的列必须来自最初发送到 select() 的列表,不是 选择本身的导出列。

您要么必须在外部保留这些列,要么通过 select.inner_columns 访问器获取它们。

下面的 session 说明了各种行为。 “.c.”任何 selectable 上的集合代表“我们可以从中选择的列”,这就是为什么使用“someselect.c.somecol”意味着您正在从该 select 语句中选择,就像一个表。

>>> from sqlalchemy import select 
>>> from sqlalchemy.sql import table, column 
 
>>> t = table('t', column('a'), column('b'), column('c')) 
 
>>> stmt1 = select([t]) 
>>> print(stmt1) 
SELECT t.a, t.b, t.c FROM t 
 
>>> print(stmt1.with_only_columns([t.c.b, t.c.a])) 
SELECT t.b, t.a FROM t 
 
>>> print(stmt1.with_only_columns([stmt1.c.b, stmt1.c.a])) 
SELECT b, a FROM (SELECT t.a AS a, t.b AS b, t.c AS c FROM t) 
 
>>> stmt1_cols = dict((c.key, c) for c in stmt1.inner_columns) 
 
>>> stmt1_cols 
{'a': <sqlalchemy.sql.elements.ColumnClause at 0x102d0e090; a>, 'c': <sqlalchemy.sql.elements.ColumnClause at 0x102de7c50; c>, 'b': <sqlalchemy.sql.elements.ColumnClause at 0x10047bb50; b>} 
 
>>> dict(t.c) 
{'a': <sqlalchemy.sql.elements.ColumnClause at 0x102d0e090; a>, 'c': <sqlalchemy.sql.elements.ColumnClause at 0x102de7c50; c>, 'b': <sqlalchemy.sql.elements.ColumnClause at 0x10047bb50; b>} 
 
>>> assert stmt1_cols == dict(t.c) 
 
>>> print(stmt1.with_only_columns([stmt1_cols['b'], stmt1_cols['a']])) 
SELECT t.b, t.a FROM t