web-dev-qa-db-ja.com

SQLiteを使用してSQLAlchemyで個別の行を返す

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

したがって、2番目の形式では正しい結果が得られますが、最初の形式では正しくありません。これはSQLiteで発生するようですが、Postgresでは発生しません。クエリオブジェクトを渡してdistinct句を適用する関数があるので、上記の2番目のアプローチを使用してすべてを書き換えることは非常に困難です。私が行方不明になっていることは明らかですか?

38
Eli Courtwright

ドキュメントによると:

存在する場合、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()

お役に立てば幸いです。

45
alecxe

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

Distinct句の引数は完全に無視されます。

テーブルから個別の名前だけが本当に必要な場合は、名前のみを明示的に選択する必要があります。

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

生成するもの:

SELECT DISTINCT tag.name AS tag_name FROM tag
20
mata