通过具有最大列值的记录过滤 Django 查询

Posted

技术标签:

【中文标题】通过具有最大列值的记录过滤 Django 查询【英文标题】:Filtering Django Query by the Record with the Maximum Column Value 【发布时间】:2011-10-24 14:53:24 【问题描述】:

有没有一种简单的方法可以根据哪条记录在列中具有最大值/最小值来过滤 Django 查询?我本质上是在问thesequestions,但在 Django 的 ORM 的特定上下文中。

例如

假设我有一个模型旨在存储每个人电话号码的历史值。

class Person(models.Model):
    name = models.CharField(max_length=100)
    phone = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)

有记录:

Person(name='Jim',phone='123-456-9870', created=datetime(2005,1,2,4,2))
Person(name='Jim',phone='329-802-9870', created=datetime(2006,9,2,7,8))
Person(name='Sue',phone='324-345-3450', created=datetime(2008,7,4,6,1))

现在假设我想找到每个人最近的电话号码。

在 SQL 中,我通常必须使用子查询来计算最大值:

SELECT p1.name, p1.phone, p1.created
FROM person_person p1, (
    SELECT name, MAX(created) AS max_created
    FROM person_person
    GROUP BY name
) AS p2
WHERE p1.name = p2.name AND p1.created = p2.max_created

Django 中是否有任何机制可以简化这一点?

我在后端使用 PostgreSQL,因此任何依赖 PostgreSQL 特定功能的想法或解决方案都会有所帮助。

【问题讨论】:

似乎在 django 上你不能做你正在寻找的东西,除非你使用原始查询 sql。检查this。由于此时您将创建的 order_by('created') 添加到查询中的 select 中,因此 distinct 不会执行任何操作。 你可以用 Django ORM 做到这一点,看我的回复:***.com/a/65898703/842572 【参考方案1】:

您可能只想在这里使用原始 SQL,raw() 管理器方法促进了这一点,允许您从查询中返回模型实例。唯一的技巧是原始查询需要包含主键。这可能对您有用(除非您将主键设置为 id 以外的其他内容):

latest_phone_numbers = Person.objects.raw('''
SELECT p1.id, p1.name, p1.phone, p1.created
FROM person_person p1, (
    SELECT name, MAX(created) AS max_created
    FROM person_person
    GROUP BY name
) AS p2
WHERE p1.name = p2.name AND p1.created = p2.max_created
''')

【讨论】:

【参考方案2】:

更新:如果您使用的是 PostgreSQL,则可以将 ORM 与 .distinct() 一起使用

来自PostgreSQL documentation:

SELECT DISTINCT ON (表达式 [, ...] ) 只保留第一行 给定表达式计算结果为等于的每组行。这 DISTINCT ON 表达式使用与 for 相同的规则进行解释 订购(见上文)。请注意,每组的“第一行”是 不可预测,除非使用 ORDER BY 来确保所需的行 首先出现。

使用 Django ORM:


Person.objects.order_by('name', '-created').distinct('name')

生成的 SQL:

select distinct on (name)
    ...
from person_person
order by name, created desc

【讨论】:

【参考方案3】:

如果您的后端是 PostgreSQL,Roman Pekar 对this 问题给出了很好的答案。

【讨论】:

以上是关于通过具有最大列值的记录过滤 Django 查询的主要内容,如果未能解决你的问题,请参考以下文章

Django:分组然后通过查询计算列值的总和

构建请求 URL 以通过同一字段多次过滤 Django 查询集

需要帮助修复 Oracle SQL 查询以返回具有最大列值的行

Django ORM,通过查询求和列值

Laravel - 查询构建器以选择具有唯一列值的多行(具有另一列的最大值)

如何设置子查询以获取具有最新日期和最大 ID 的单个记录?