2011-09-29 38 views
0

我想要的是TableA中的计数来自TableB的列,但当然我需要TableB中的每个计数都与之关联的项目。最好用代码解释:sqlalchemy加入的别名没有来自两个表的列

表A和B是模型对象。

我试图按照this syntax尽我所能。

试图运行此查询:

sq = session.query(TableA).join(TableB).\ 
     group_by(TableB.attrB).subquery() 

countA = func.count(sq.c.attrA) 
groupB = func.first(sq.c.attrB) 

print session.query(countA, groupB).all()  

但它给了我一个AttributeError(SQ没有attrB)

我是新来的SA,我觉得很难学。 (欢迎使用推荐的教育资源链接)

+0

'FIRST()'不是一个sql标准函数,你连接了哪些DBMS? – SingleNegationElimination

+0

@TokenMacGuy好的。那么我的问题适用,如果你用'最大'替换'第一',但没有理由比较应该是相同的所有值。我正在使用mySQL引擎。 – Paul

回答

2

当您从select语句创建子查询时,可以从中访问的列必须位于columns子句中。举个例子如下语句:

select x, y from mytable where z=5 

如果我们想要做一个子查询,然后GROUP BY“Z”,这不会是合法的SQL:

select * from (select x, y from mytable where z=5) as mysubquery group by mysubquery.z 

由于“Z”不“mysubquery”的列子句(它也是非法的,因为'x'和'y'也应该在GROUP BY中,但这是一个不同的问题)。

SQLAlchemy的工作方式完全相同。当你说查询(..)。subquery(),或者在核心可选结构上使用alias()函数时,这意味着你将你的SELECT语句包装在括号中,给它一个(通常是生成的)名字,并给它一个新的.c。只有那些位于“列”子句中的列才是真正的SQL。

所以在这里你需要确保TableB,至少是你在外部处理的列是可用的。您还可以限制列子句只是那些列,你需要:

sq = session.query(TableA.attrA, TableB.attrB).join(TableB).\ 
     group_by(TableB.attrB).subquery() 

countA = func.count(sq.c.attrA) 
groupB = func.first(sq.c.attrB) 

print session.query(countA, groupB).all()  

注意的是,上面的查询可能只适用于MySQL的,如一般的SQL是非法的引用不属于集合的一部分的任何列函数或GROUP BY的一部分,当使用分组时。 MySQL在这方面有一个更轻松(和马虎)的系统。

编辑:如果你想要的结果,而不零点:

import collections 

letter_count = collections.defaultdict(int) 
for count, letter in session.query(func.count(MyClass.id), MyClass.attr).group_by(MyClass.attr): 
    letter_count[letter] = count 

for letter in ["A", "B", "C", "D", "E", ...]: 
    print "Letter %s has %d elements" % letter_count[letter] 

注letter_count [someletter]默认为零否则不填充。

+0

由于“first”不起作用,你能想到一种廉价/惯用的方法来获得分组值吗?它与这个问题密切相关:http://stackoverflow.com/questions/7585892/looking-for-a-slight-variant-of-group-by(如果你认为它是有保证的,我很乐意提交另一个问题) – Paul

+0

其他问题非常尴尬,因为您希望“0”不存在的值。如果你只能接收来自数据库的行,填充到一个结构中,并且为不在结果集中的那些设置“0”,那么它就不那么笨拙了。否则,为了使它与SQL直接相关,你必须创建一个“A”,“B”,“C等人工列表,这就是为什么这些UNION在那里。” – zzzeek

+0

我愿意放弃返回“0”如果我能把它作为纯粹的SA ORM语法。 – Paul