从表字段中选择不同的值


104

我正在努力使自己的头转向Django的ORM。我想做的是获取表中字段中不同值的列表..等效于以下之一:

SELECT DISTINCT myfieldname FROM mytable

(或者)

SELECT myfieldname FROM mytable GROUP BY myfieldname

我至少想在使用原始sql之前以Django方式进行操作。例如,有一个表:

身份证,街道,城市

赫尔大街1号

赫尔其他街2号

3,Bibble Way,莱斯特

4,另一种方式,莱斯特

Londidium高街5号

我想得到:

赫尔,莱斯特,朗迪丁。

Answers:


202

假设您的模特是“商店”

class Shop(models.Model):
    street = models.CharField(max_length=150)
    city = models.CharField(max_length=150)

    # some of your models may have explicit ordering
    class Meta:
        ordering = ('city')

由于您可能设置了Metaclass ordering属性,因此在使用时,可以order_by()不使用任何参数来清除任何顺序distinct()。请参阅()下的文档order_by

如果您不希望对查询应用任何排序,甚至不希望使用默认排序,请调用不带参数的order_by()。

distinct()在注释中讨论了distinct()与订购一起使用的问题。

要查询数据库,您只需调用:

models.Shop.objects.order_by().values('city').distinct()

它返回字典

要么

models.Shop.objects.order_by().values_list('city').distinct()

这将返回ValuesListQuerySet,您可以将其转换为list。您还可以添加flat=Truevalues_list扁平化的结果。

另请参阅:通过字段获取Queryset的不同值


29
其实可行。然而!我无法在所有模型上使用它。奇怪的是,它只对某些产品有效,而对其他产品则无效。对于那些具有元顺序的人,它不起作用。因此,您必须先清除queryset上的顺序。models.Shop.objects.order_by()。values('city')。distinct()
2010年

2
重要的是要注意,values_list它实际上不会返回列表。它返回类似查询集的内容。我发现在values_list调用周围始终使用list()很有用。
恐龙

8
values_list返回ValuesListQuerySet,它是一个迭代器。强制转换为列表可能很方便,但是当必须一次评估所有行时(特别是对于大型数据集),也会影响性能。
彼得·基尔丘克

3
Meta: ordering = ()django orm和objects.distinct()vs. 的“功能” objects.ordering().distinct()使我们困惑了数小时。该产品上应该贴有消费者安全警告标贴;)我们可能会制定无元订购属性政策,以防止将来出现头疼的情况。
滚刀

您可以通过不使用任何参数来关闭Metaordering并解决问题。它位于QuerySet API文档中的“ 如果您不希望对查询应用任何排序,甚至不希望使用默认排序,请不使用任何参数进行调用distinctorder_by()order_by()order_by()
Mark Mikofski 2014年

11

除了jujule仍然非常相关的答案外,我发现还很重要的一点是,也要意识到jujuleorder_by()distinct("field_name")查询的影响。但是,这是仅Postgres的功能!

如果您使用的是Postgres,并且定义了查询所要区分的字段名,则order_by()需要以相同的序列名(或多个字段名)以相同的顺序开头(之后可能会有更多的字段)。

注意

指定字段名称时,必须在QuerySet中提供order_by(),并且order_by()中的字段必须以相同的顺序从distinct()中的字段开始。

例如,SELECT DISTINCT ON(a)为列a中的每个值提供第一行。如果您不指定订单,则会得到一些任意行。

如果您想提取例如您知道在其有商店的城市的列表,则必须将jujule的示例进行以下调整:

# returns an iterable Queryset of cities.
models.Shop.objects.order_by('city').values_list('city', flat=True).distinct('city')  

2

例如:

# select distinct code from Platform where id in ( select platform__id from Build where product=p)
pl_ids = Build.objects.values('platform__id').filter(product=p)
platforms = Platform.objects.values_list('code', flat=True).filter(id__in=pl_ids).distinct('code')
platforms = list(platforms) if platforms else []
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.