Когда вы делаете подзапрос из оператора select, столбцы, к которым можно получить к нему доступ, должны находиться в предложении столбцов.Возьмем, к примеру, следующее утверждение:
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 работает точно так жепуть.Когда вы говорите query (..). 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 имеет более расслабленную (и небрежную) систему.
edit: если вы хотите, чтобы результаты были без нулей:
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] по умолчанию обнуляется, если в противном случаене заселен.