Django:如何获取每个项目的最新行?

时间:2016-11-28 00:46:32

标签: python sql django

我的问题类似于这个问题: How to select only the latest rows for each user? 但我正在用Django实现这一点。

在下面的例子中(我从上面的问题中借用),我只需要为每个用户提取最后一行。另外,就我而言,我只想获取特定user_ids列表的行。

id  | user_id | period_id | completed_on
----------------------------------------
1   | 1       | 1         | 2010-01-01
2   | 2       | 1         | 2010-01-10
3   | 3       | 1         | 2010-01-13
4   | 1       | 2         | 2011-01-01
5   | 2       | 2         | 2011-01-03
6   | 2       | 3         | 2012-01-13
... | ...     | ...       | ...

如果user_list为[1,2],我想得到这样的结果:

id  | user_id | period_id | completed_on
----------------------------------------
4   | 1       | 2         | 2011-01-01
6   | 2       | 3         | 2012-01-13

我是用过滤器编写的,但无法找到正确的方法。

PeriodTable.objects.filter(user__in=user_list, period_id=max(....?)).values(...)

2 个答案:

答案 0 :(得分:0)

首先是一个小帮助函数,用于将一个int数组转换为一个sql IN子句的参数。

def to_sql_in(arr):
    return ','.join(map(str, arr))

然后您可以使用cursor直接查询您的数据库,因为在这种情况下我认为过滤器不够。

user_list = [1, 2]

with connection.cursor() as cursor:
    cursor.execute('''SELECT t.Id, t.User_Id, t.Period_Id, t.Completed_On
                      FROM Table1 t
                      JOIN (SELECT Max(completed_on) Max_Completed_On, t.User_Id
                      FROM Table1 t
                      GROUP BY t.User_Id) t2
                      ON t.User_Id = t2.User_Id AND t.Completed_On = t2.Max_Completed_On
                      WHERE t.User_Id IN ({0})'''.format(to_sql_in(user_list)))

    r = cursor.fetchall()
    columns = [col[0] for col in cursor.description]
    print [dict(zip(columns, row)) for row in r]

答案 1 :(得分:0)

如果通过“last”指的是每个用户的最大completed_on,并且此列未排序,则可能您必须直接使用SQL(如已建议的那样)。但是,如果“last”表示每个用户的表的最后一个条目,则可以直接使用Django聚合API解决问题。假设您的模型是M

from django.db.models import Max
q = M.objects.filter(user_id__in=users_list)
max_ids = q.values('user_id').annotate(Max('id')).values_list('id__max')
result = M.objects.filter(id__in=max_ids)

第三行只按user_id分组,但记住每个组的最大id行,并创建这些ID的列表。最后,结果是带有这些ID的行集。

我强调,如果您想为每个用户获取数据库中的最后一个条目,此解决方案只能