我想要的只是TableA中按TableB列的一个列的计数,但当然我需要TableB中与每个计数相关联的项目。用代码更好地解释:
TableA和B是Model对象。
我尽力遵循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 :(得分: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”的columns子句中(因为'x'和'y'也应该在GROUP BY中,所以它也是非法的,但这是一个不同的问题)。
SQLAlchemy的工作方式完全相同。当你说查询(..)。子查询(),或在核心可选构造上使用alias()函数时,它意味着你将SELECT语句包装在括号中,给它一个(通常是生成的)名称,然后给它一个新的.c。只有那些列在“columns”子句中的集合,就像真正的SQL一样。
因此,您需要确保TableB(至少是您在外部处理的列)可用。您还可以将columns子句限制为所需的列:
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]
note letter_count [someletter]默认为零,否则不会填充。