【问题标题】:Retrieving distinct records based on a column on Django根据 Django 上的列检索不同的记录
【发布时间】:2011-06-11 00:40:30
【问题描述】:

我需要检索下表的记录列表,其中的名称具有不同的值:

Class C:

name                value
A ------------------ 10
A ------------------ 20
A ------------------ 20
B ------------------ 50
C ------------------ 20
D ------------------ 10
B ------------------ 10
A ------------------ 30

我需要去掉 name 的所有重复值,只显示以下内容:

name                value
A ------------------ 30
B ------------------ 10
C ------------------ 20
D ------------------ 10

如您所见,它几乎看起来像一个 python 集。我可能可以使用 Python 生成集合,但我想知道 Django 的 ORM 是否具有此功能。

我尝试使用 distinct,但它不接受任何参数来指定哪个列必须具有不同的值。知道如何让这个查询工作吗?

【问题讨论】:

  • 你只是想要每个名字的第一个值,还是什么?
  • 你应该选择一个,因为第一个和最后一个值不同。你真的想要任意随机性吗?
  • 我实际上需要最后一个值。但是对于这个例子,我把它放在第一位,因为我认为没有区别。

标签: django distinct


【解决方案1】:

.distinct() 是工具,但这是我必须使用的语法:

Model.objects.values_list('name', flat=True).distinct()

这样你只能得到一个值列表 [A,B,C,D],而不是对象本身。

【讨论】:

  • 这仅适用于 PostgreSQL。如果你使用的是 MySQL 或 SQLite,那你就不走运了。
  • @SerafimS。这适用于 MySQL 和 SQLite。做 distinct on 对 PostgreSQL 不起作用,但是这个答案中的查询并没有做一个 distinct on!
【解决方案2】:

sqlite distinct 的问题是它在所有返回值上都不同。要区分一个列名,例如:'url' 从表中获取所有唯一 url,但也获取其余数据,请使用子查询。

子查询获取 url 的 ID,然后使用它对这些想法进行另一个查询。这当然不如常规的 distinct 快。

link_ids = (
    Resources
    .values('url')
    .distinct()
    .annotate(
        occurrences=Count('url'),  # make unique 'urls' only occur once.
        pk=Min('pk')  # return pk of first occurrence
    )
)
broken_links_qs = (
    Resources.filter(id__in=Subquery(link_ids.values('pk')))
)

(在给出之前的答案时,django 还没有子查询功能。)

【讨论】:

  • 我应该在哪里包含 Count 和 Min from?
【解决方案3】:

这不是很优雅,但它可以在大约一行中完成工作:

# Fetch all rows to limit num of queries
all_rows = MyModel.objects.all()

# Query against the full list to return a list of objects
item_list = [all_rows.filter(myfield=item['myfield']).last() for item in MyModel.objects.values('myfield').distinct()]

这将检索您正在对其执行 DISTINCT 的每个值的完整模型实例。一些用例可能需要不同的过滤。

然后只需使用item_list 上每个项目中的namevalue 属性来获取您的不同数据。

【讨论】:

    【解决方案4】:

    你也可以像这样使用 raw:

    queryraw = C.objects.raw('SELECT name, value FROM prj_c GROUP BY name')

    或添加一个 ORDER BY 以获得任何组的更高值:

    queryraw = C.objects.raw('SELECT name, value FROM prj_c GROUP BY name ORDER BY value')

    在任何情况下,您都可以拥有list() 个对象。

    这里有有用的文档:https://docs.djangoproject.com/en/2.0/topics/db/sql/

    【讨论】:

      【解决方案5】:

      使用以下语法应该可以解决您的问题。 values('name', 'value').distinct()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多