web-dev-qa-db-fra.com

Renvoyer des lignes distinctes dans SQLAlchemy avec SQLite

La méthode Query.distinct de SQLAlchemy se comporte de manière incohérente:

>>> [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

Le deuxième formulaire donne donc le résultat correct, mais pas le premier. Cela semble se produire avec SQLite mais PAS avec Postgres. J'ai une fonction à laquelle est passé un objet de requête pour qu'une clause distinct lui soit appliquée, il serait donc très difficile de tout réécrire en utilisant la deuxième approche ci-dessus. Y a-t-il quelque chose d'évident qui me manque?

38
Eli Courtwright

Selon les documents:

Lorsqu'il est présent, le dialecte Postgresql rendra une construction DISTINCT ON (>).

Donc, passer des expressions de colonne à distinct() ne fonctionne que pour PostgreSQL (car il y a DISTINCT ON).

Dans l'expression session.query(Tag).distinct(Tag.name).count() sqlalchemy ignore Tag.name Et produit la requête (distincte sur tous les champs):

SELECT DISTINCT tag.country_id AS tag_country_id, tag.name AS tag_name 
FROM tag

Comme vous l'avez dit, dans votre cas, distinct(Tag.name) est appliqué - donc au lieu de simplement count() pensez à utiliser ceci:

session.query(Tag).distinct(Tag.name).group_by(Tag.name).count()

J'espère que ça t'as aidé.

45
alecxe

Lorsque vous utilisez session.query(Tag), vous recherchez toujours l'ensemble de l'objet Tag, donc si votre table contient d'autres colonnes, cela ne fonctionnera pas.

Supposons qu'il existe une colonne id, puis la requête

sess.query(Tag).distinct(Tag.name)

produira:

SELECT DISTINCT tag.id AS tag_id, tag.name AS tag_name FROM tag

L'argument de la clause distinct est complètement ignoré.

Si vous ne voulez vraiment que les noms distincts de la table, vous devez explicitement sélectionner uniquement les noms:

sess.query(Tag.name).distinct()

produit:

SELECT DISTINCT tag.name AS tag_name FROM tag
20
mata