如何防止sqlalchemy为CTE的列名添加前缀?

时间:2013-03-14 17:39:03

标签: python python-2.7 sqlalchemy

考虑通过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_[column name];这是因为SQLAlchemy在我的列名前加上CTE名称。我希望SQLAlchemy在生成列名时不要使用我的CTE名称,但由于我有很多列,所以我不希望在子查询中单独列出它们。离开CTE名称会使我的列名(它们自己足够长)更短,更易读;我可以保证列是唯一的。我怎么能这样做?

将Python 2.7.3与SQLAlchemy 0.7.10一起使用。

1 个答案:

答案 0 :(得分:1)

你不是太具体了什么&#34; x _&#34;在这里,但如果这是最终结果,请使用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

编辑:我无法重现&#34; x _&#34;这里。这是一个测试:

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>,没有&#34; x&#34;前缀。如果您可以请指定SQLAlchemy版本信息并完整填写您的示例,我可以按原样运行它以重现您的问题。