【问题标题】:Select distinct values from a table field从表字段中选择不同的值
【发布时间】:2011-01-28 19:38:57
【问题描述】:

我很难理解 Django 的 ORM。我想要做的是在我的表上的一个字段中获取不同值的列表......相当于以下之一:

SELECT DISTINCT myfieldname FROM mytable

(或替代)

SELECT myfieldname FROM mytable GROUP BY myfieldname

在诉诸原始 sql 之前,我至少希望以 Django 方式进行。 例如,使用表格:

id,街道,城市

赫尔大街 1 号

赫尔其他街 2 号

3,圣经路,莱斯特

4,另一种方式,莱斯特

5, High Street, Londidium

我想得到:

赫尔、莱斯特、伦蒂迪姆。

【问题讨论】:

    标签: django django-queryset django-orm query-performance


    【解决方案1】:

    如果您使用 PostgreSQL 并且只想通过一个可以使用的特定字段来获取和区分

    MyModel.objects.values('name').annotate(Count('id')).order_by()
    

    此查询集向我们返回其“名称”字段是唯一的行,其中具有相同名称的行的计数

    <QuerySet [{'name': 'a', 'id__count': 2}, {'name': 'b', 'id__count': 2}, {'name': 'c', 'id__count': 3}>
    

    我知道返回的数据不完整,有时不满意但有时很有用

    document reference

    【讨论】:

      【解决方案2】:

      除了仍然非常相关的answer of jujule,我发现了解order_by()distinct("field_name") 查询的影响也很重要。 不过,这是 Postgres 独有的功能!

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

      注意

      当您指定字段名称时,您必须在 QuerySet,并且 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')  
      

      【讨论】:

      • 非常感谢.distinct("field_name")
      【解决方案3】:

      假设您的模型是“商店”

      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',)
      

      由于您可能设置了Metaordering 属性集(它是元组或列表),因此您可以在使用distinct() 时使用不带参数的order_by() 来清除任何排序。请参阅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=True 添加到values_list 以展平结果。

      另见:Get distinct values of Queryset by field

      【讨论】:

      • 实际上可行。然而!我无法让它在我的所有模型上工作。奇怪的是,它对某些人有效,但对其他人无效。对于那些有 Meta 排序的人,它不起作用。因此,您必须首先清除查询集上的排序。 models.Shop.objects.order_by().values('city').distinct()
      • 请注意values_list 实际上并不返回一个列表。它返回类似查询集的东西。我发现总是在 values_list 调用周围使用 list() 很有用。
      • values_list 返回 ValuesListQuerySet ,它是一个迭代器。强制转换为列表可能很方便,但在必须同时评估所有行时也会影响性能,尤其是对于大型数据集。
      • django orm 和 objects.distinct()objects.ordering().distinct()Meta: ordering = ()“功能”让我们困惑了好几个小时。该产品上应该有一个消费者安全警告标签;)我们可能会制定一个无元排序属性的政策,以防止未来的头疼。
      • 您可以关闭Metaordering 并使用不带参数的order_by() 解决distinct 的问题。它位于 order_by() 下的 QuerySet API 文档中“如果您不希望对查询应用任何排序,甚至不希望使用默认排序,请在不带参数的情况下调用 order_by()”跨度>
      【解决方案4】:

      举例:

      # 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 []
      

      【讨论】:

        猜你喜欢
        • 2019-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-23
        • 1970-01-01
        • 2022-11-17
        • 1970-01-01
        • 2015-08-25
        相关资源
        最近更新 更多