51

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应用一个子句,因此使用上面的第二种方法重写所有内容将非常困难。我有什么明显的遗漏吗?

4

2 回答 2

67

根据文档:

如果存在,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()

希望有帮助。

于 2013-06-20T21:15:22.137 回答
36

当您使用时,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
于 2013-06-20T21:25:09.013 回答