如何防止sqlalchemy为CTE的列名添加前缀?
考虑一下下面这个用SQLAlchemy写的查询。
# Create a CTE that performs a join and gets some values
x_cte = session.query(SomeTable.col1
,OtherTable.col5
) \
.select_from(SomeTable) \
.join(OtherTable, SomeTable.col2 == OtherTable.col3)
.filter(OtherTable.col6 == 34)
.cte(name='x')
# Create a subquery that splits the CTE based on the value of col1
# and computes the quartile for positive col1 and assigns a dummy
# "quartile" for negative and zero col1
subquery = session.query(x_cte
,literal('-1', sqlalchemy.INTEGER).label('quartile')
) \
.filter(x_cte.col1 <= 0)
.union_all(session.query(x_cte
,sqlalchemy.func.ntile(4).over(order_by=x_cte.col1).label('quartile')
)
.filter(x_cte.col1 > 0)
) \
.subquery()
# Compute some aggregate values for each quartile
result = session.query(sqlalchemy.func.avg(subquery.columns.x_col1)
,sqlalchemy.func.avg(subquery.columns.x_col5)
,subquery.columns.x_quartile
) \
.group_by(subquery.columns.x_quartile) \
.all()
抱歉内容有点长,但这和我实际的查询很相似。在我的真实代码中,我给我的CTE(公共表表达式)起了个更详细的名字,而且我的CTE有更多的列需要计算平均值。(实际上,这还是一个加权平均,权重是CTE中的一列。)
真正的“问题”只是想让我的代码更清晰、更简短。(是的,我知道这个查询已经很复杂,难以阅读,但客户坚持要这些数据。)注意在最终的查询中,我必须用subquery.columns.x_[列名]
来引用我的列;这是因为SQLAlchemy在我的列名前加上了CTE的名字。我希望SQLAlchemy在生成列名时能不加上CTE的名字,但由于我有很多列,我不想在子查询中一个个列出它们。如果去掉CTE的名字,列名(本身就已经很长了)会变得更短、更易读;我可以保证这些列名是唯一的。我该怎么做呢?
我使用的是Python 2.7.3和SQLAlchemy 0.7.10。
1 个回答
1
你没有具体说明“x_”指的是什么,但如果这是最终结果,可以用label()给结果的列起个你喜欢的名字:
row = session.query(func.avg(foo).label('foo_avg'), func.avg(bar).label('bar_avg')).first()
foo_avg = row['foo_avg'] # indexed access
bar_avg = row.bar_avg # attribute access
补充:我无法重现这里的“x_”。这是一个测试:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class A(Base):
__tablename__ = "a"
id = Column(Integer, primary_key=True)
x = Column(Integer)
y = Column(Integer)
s = Session()
subq = s.query(A).cte(name='x')
subq2 = s.query(subq, (subq.c.x + subq.c.y)).filter(A.x == subq.c.x).subquery()
print s.query(A).join(subq2, A.id == subq2.c.id).\
filter(subq2.c.x == A.x, subq2.c.y == A.y)
在上面,你可以看到我可以毫无问题地引用subq2.c.<colname>
,前面没有“x”。如果可以的话,请提供SQLAlchemy的版本信息,并完整填写你的例子,这样我就可以直接运行你的代码,看看能否重现你的问题。