Django的。数据库查询:对于一个字段是不同的

时间:2011-11-08 15:31:55

标签: sql django django-models django-queryset django-mssql

我在DB中有以下字段和数据:

FirstName     LastName    Date

John          Davis       10-10-2011
Joe           Gray        20-09-2011
Ann           Davis       03-04-2010
Ann           Bovis       01-04-2010

如何从包含结果中包含的所有其他字段的最新日期和唯一姓氏的DB 3项目中进行选择。这意味着如果有多个具有LastName Davis的项目,则结果应该只有一个具有最新日期。 甚至不知道如何在纯SQL上做到这一点 - 而且Django看起来根本不可能。

EDIT1。 SQL QUERY。

我在纯SQL上写了一个查询:

SELECT TOP 3 *
FROM peopleTable as a1
WHERE  (select count(*)FROM peopleTable as a2 where a2.LastName=a1.LastName and a2.Date > a1.Date)<=0
ORDER by Date desc

我想如果我在django中使用这个查询就像纯SQL那样会更好。

3 个答案:

答案 0 :(得分:1)

查看aggregation

上的文档 猜猜你想要像

这样的东西
Item.objects.values("lastname").annotate(
    date=Max("date"), firstname=Max("firstname"
    ).order_by()

您必须按聚合查询中包含的所有字段进行聚合或分组。在你的情况下,你想要max(数据)和group_by姓氏。你必须为firstname选择一些聚合,比如max

请注意,在charfields聚合上似乎有一个postgres bug

答案 1 :(得分:1)

你可以这样做:

  

最新日期和唯一姓氏

  

所有其他字段

但你不能两者都做。如果你想获得姓氏戴维斯的最新日期,应该检索哪些其他字段,firstname = John或firstname = Ann?

猜测您希望结果如下所示:

FirstName     LastName    Date

John          Davis       10-10-2011
Joe           Gray        20-09-2011
Ann           Bovis       01-04-2010

安·戴维斯因为她不是桌上最新的戴维斯而离开了。正确的吗?

在这种情况下,您的原始SQL看起来像:

SELECT FirstName, LastName, Date
FROM
Table T1
WHERE
NOT EXISTS (
SELECT * FROM Table T2 WHERE T2.LastName=T1.LastName AND T2.Date > T1.Date
)

您可以使用Item.objects.raw()选项在Django中编写。您也可以使用extra(where=…)

答案 2 :(得分:0)

你无法用查询真正做到这一点;这对SQL来说太过逻辑了。但是,根据字典键是独一无二的事实,你可以通过一点点聪明才能得到你想要的东西。

首先,获取按日期升序排序的查询集。这可能看起来违反直觉,因为你想要最新的日期,但在接下来的步骤中它会有意义:

qs = SomeModel.objects.order_by('date')

接下来,我们将在列表解析中使用它来创建(key, value)元组(在Python 3+中,你实际上可以进行字典理解,但是因为我认识的人实际上并没有使用Python 3+,我用这种方式详细说明:

qs_list = [(item.last_name, item) for item in qs]

最后,我们将这个元组列表转换为字典:

items = dict(qs_list)

现在您将拥有一个字典,其中每个last_name键都是唯一的。由于字典键必须是唯一的,因此每个重复的姓氏的最后一个值是实际使用它的那个。由于列表是按日期升序排序的,因此最后一个值是“最新的”。

您可以将此词典转换回直接列表,或者只是按原样迭代它。唯一的问题是你不再处理QuerySet,所以你不能再做任何进一步的过滤器等等。请记住这一点,并在完全构建查询后再执行这些步骤。

当然,如果您愿意,可以将所有这些都作为一个班轮:

items = dict([(item.last_name, item) for item in SomeModel.objects.order_by('date')])