ChatGPT解决这个技术问题 Extra ChatGPT

在 django 中选择 DISTINCT 个别列?

我很好奇是否有任何方法可以在 Django 中进行查询,而不是下面的“SELECT * FROM...”。我正在尝试做一个“SELECT DISTINCT columnName FROM ...”。

具体来说,我有一个看起来像这样的模型:

class ProductOrder(models.Model):
   Product  = models.CharField(max_length=20, promary_key=True)
   Category = models.CharField(max_length=30)
   Rank = models.IntegerField()

其中 RankCategory 内的排名。我希望能够遍历所有类别,对该类别中的每个等级进行一些操作。

我想首先获取系统中所有类别的列表,然后查询该类别中的所有产品并重复,直到处理完每个类别。

我宁愿避免使用原始 SQL,但如果我必须去那里,那很好。虽然我以前从未在 Django/Python 中编写过原始 SQL。


T
Tomasz Zieliński

从数据库中获取不同列名列表的一种方法是将 distinct()values() 结合使用。

在您的情况下,您可以执行以下操作来获取不同类别的名称:

q = ProductOrder.objects.values('Category').distinct()
print q.query # See for yourself.

# The query would look something like
# SELECT DISTINCT "app_productorder"."category" FROM "app_productorder"

这里有几件事要记住。首先,这将返回一个行为不同于 QuerySetValuesQuerySet。当您访问 q 的第一个元素(上图)时,您将获得 dictionary,而不是 ProductOrder 的实例。

其次,最好阅读文档中有关使用 distinct()warning note。上面的示例可以使用,但 distinct()values() 的所有组合可能都不会。

PS:对模型中的字段使用小写名称是个好主意。在您的情况下,这意味着重写您的模型,如下所示:

class ProductOrder(models.Model):
    product  = models.CharField(max_length=20, primary_key=True)
    category = models.CharField(max_length=30)
    rank = models.IntegerField()

下面描述的方法现在在 django 1.4 中可用,如果您需要具有字段感知不同的 ProductOrder 实例,则很好;-)
我想知道如何修改此代码,以便它也适用于 where 语句。像 select distinct(app_productorder.category) from app_productorder where app_productorder.rank <30;
您如何将其转换为正常的查询集?
关于 sql 中 select distinct on 的好提示:geekytidbits.com/postgres-distinct-on
H
Henry Woody

实际上很简单如果您使用的是 PostgreSQL,只需使用 distinct(columns) (documentation)。

Productorder.objects.all().distinct('category')

请注意,此功能自 1.4 以来已包含在 Django 中


@lazerscience,@Manoj Govindan:对不起,你是对的。看来我已经修补了 Django 以添加该功能。我已经添加了补丁的链接
这现在在 Django SVN 中,将在 Django 1.4 中
注意:除非你使用 PostgreSQL,否则你不能给 distinct() 一个参数。最好坚持上面接受的解决方案。
在测试中,这是 can_distinct_on_fields,它似乎是 Postgres-only
加 1,但此处不需要 all()
S
SuperNova

用户使用该字段排序,然后进行区分。

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()

被低估的答案!如果你能更好地解释它会更好。我遇到了与订购有关的问题。
M
Mark Chackerian

其他答案很好,但这更简洁一些,因为它只给出了从 DISTINCT 查询中获得的值,而没有来自 Django 的任何内容。

>>> set(ProductOrder.objects.values_list('category', flat=True))
{u'category1', u'category2', u'category3', u'category4'}

或者

>>> list(set(ProductOrder.objects.values_list('category', flat=True)))
[u'category1', u'category2', u'category3', u'category4']

而且,它可以在没有 PostgreSQL 的情况下工作。

这比使用 .distinct() 效率低,假设数据库中的 DISTINCT 比 python set 快,但它非常适合在 shell 周围闲逛。

更新:这个答案非常适合在开发期间在 Django shell 中进行查询。不要在生产中使用此解决方案,除非您绝对确定在应用 set 之前您将始终获得少量结果。否则,从性能的角度来看,这是一个糟糕的主意。


values_list 不会将 DISTINCT 放在 sql 查询中,因此如果有的话,这会带来多个值。
从性能的角度来看,这是一个糟糕的主意!
是的——如果你有一张非小桌子,不要在生产中这样做!