考虑以下通过 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 一起使用。