Возвращение отдельных строк в SQLAlchemy с помощью SQLite
SQLAlchemy Query.distinct ведет себя непоследовательно:
>>> [tag.name for tag in session.query(Tag).all()]
[u'Male', u'Male', u'Ninja', u'Pirate']
>>> session.query(Tag).distinct(Tag.name).count()
4
>>> session.query(Tag.name).distinct().count()
3
Таким образом, вторая форма дает правильный результат, но первая форма - нет. Это похоже на SQLite, но не с Postgres. У меня есть функция, которая передала объект запроса, чтобы применить к ней предложение distinct
, поэтому было бы очень сложно переписать все, чтобы использовать второй подход выше. Есть ли что-то очевидное, что мне не хватает?
Ответы
Ответ 1
Согласно документам:
При наличии диалекта Postgresql будет отображаться DISTINCT ON ( > ).
Итак, передача выражений столбца в distinct()
работает только для PostgreSQL (потому что есть DISTINCT ON
).
В выражении session.query(Tag).distinct(Tag.name).count()
sqlalchemy игнорирует Tag.name
и выдает запрос (отличный от всех полей):
SELECT DISTINCT tag.country_id AS tag_country_id, tag.name AS tag_name
FROM tag
Как вы сказали, в вашем случае применяется distinct(Tag.name)
- поэтому вместо просто count()
подумайте об этом:
session.query(Tag).distinct(Tag.name).group_by(Tag.name).count()
Надеюсь, что это поможет.
Ответ 2
Когда вы используете session.query(Tag)
, вы всегда запрашиваете весь объект Tag
, поэтому, если ваша таблица содержит другие столбцы, это не сработает.
Предположим, что существует столбец id
, тогда запрос
sess.query(Tag).distinct(Tag.name)
будет производить:
SELECT DISTINCT tag.id AS tag_id, tag.name AS tag_name FROM tag
Аргумент отдельного предложения полностью игнорируется.
Если вам действительно нужны только отдельные имена из таблицы, вы должны явно выбрать только имена:
sess.query(Tag.name).distinct()
дает:
SELECT DISTINCT tag.name AS tag_name FROM tag