2013-06-20 2 views
21

SQLAlchemy в Query.distinct ведет себя непоследовательно:Возвращение отдельных строк в SQLAlchemy с методом SQLite

>>> [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, поэтому было бы очень сложно переписать все, чтобы использовать второй подход выше. Есть ли что-то очевидное, что мне не хватает?

ответ

23

Согласно документации:

Когда они присутствуют, говор Postgresql будет оказывать отчетливую ПО (>) построить.

Таким образом, проходя выражения столбцов 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() 

Надеюсь, что это поможет.

+1

Спасибо; Я видел этот комментарий в документах о 'DISTINCT ON', но так как документы явно не говорили« и это единственный способ, которым это работает »или что-то в этом роде, я не понимал, что это подразумевалось. –

11

Когда вы используете 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 
Смежные вопросы