Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Псевдоним, присоединенный к sqlalchemy, не имеет столбцов из обеих таблиц

Автор вопроса: PaulОтветов: 1

Все, что мне нужно, это счет из таблицы A, сгруппированный по столбцу из таблицы B, но, конечно, мне нужен элемент из таблицы B, с которым связан каждый счетчик. Лучше объяснить кодом:

TableA и B являются объектами модели.

Я стараюсь следовать этому синтаксису, насколько это возможно. могу.

Пытаюсь запустить этот запрос:

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, и мне трудно учиться. (ссылки на рекомендуемые образовательные ресурсы приветствуются!)

  • FIRST() не является стандартной функцией sql, к какой СУБД вы подключаетесь? SingleNegationElimination 29.09.2011
  • @TokenMacGuy Хорошо. Ну, мой вопрос применим, если вы замените "первый" на "макс", но нет причин сравнивать все значения, которые должны быть одинаковыми. Я использую движок mySQL. Paul 29.09.2011

pythonsqlalchemyjoingroup-by

Ответы

Ответ 1 · рейтинг 3 · zzzeek

Когда вы делаете подзапрос из оператора 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 работает точно так же. Когда вы говорите query(..).subquery() или используете функцию alias() в основной выбираемой конструкции, это означает, что вы заключаете свой оператор SELECT в круглые скобки, давая ему (обычно сгенерированное) имя и давая ему новый .с. коллекция, в которой есть только те столбцы, которые находятся в предложении "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 в этом отношении более расслабленная (и неаккуратная) система.

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]

обратите внимание, что letter_count[someletter] по умолчанию равен нулю, если в противном случае не заполнено.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы