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?
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é.
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