Django filter查询获取每位员工最新记录的实现方法
问题描述
我有一张名为employee的员工数据表,表结构与存量数据如下:
Employee表现有数据:
empid name status created_datetime EMP001 NAMEA STATUS-B 2022-06-13 14:00:00 EMP001 NAMEA STATUS-A 2022-06-13 13:00:00 EMP002 NAMEB STATUS-B 2022-06-13 12:00:00 EMP003 NAMEC STATUS-A 2022-06-13 11:30:00 EMP001 NAMEA STATUS-C 2022-06-13 11:00:00 EMP001 NAMEA STATUS-D 2022-06-13 10:00:00 EMP003 NAMEC STATUS-B 2022-06-13 09:00:00
需要查询获取每位员工对应的最新一条记录,预期返回结果如下:
empid name status created_datetime EMP001 NAMEA STATUS-B 2022-06-13 14:00:00 EMP002 NAMEB STATUS-B 2022-06-13 12:00:00 EMP003 NAMEC STATUS-A 2022-06-13 11:30:00
即返回每个empid对应的created_datetime值最大的记录,要求使用Django filter相关语法实现。
实现方案
首先假设Employee模型定义如下:
from django.db import models class Employee(models.Model): empid = models.CharField(max_length=20, verbose_name="员工ID") name = models.CharField(max_length=50, verbose_name="员工姓名") status = models.CharField(max_length=20, verbose_name="员工状态") created_datetime = models.DateTimeField(verbose_name="记录创建时间")
方法1:子查询匹配(兼容所有数据库版本)
先分组查询每个员工ID对应的最新记录创建时间,再通过组合条件过滤出匹配的记录:
from django.db.models import Max, Q # 查出每个empid对应的最新创建时间 emp_latest_time = Employee.objects.values('empid').annotate( latest_time=Max('created_datetime') ) # 构造匹配条件 query_filter = Q() for item in emp_latest_time: query_filter |= Q( empid=item['empid'], created_datetime=item['latest_time'] ) # 拿到最终结果 result = Employee.objects.filter(query_filter)
方法2:窗口函数查询(Django 2.0+,数据库支持窗口函数时推荐,效率更高)
通过窗口函数给同个员工的记录按创建时间倒序编号,过滤出编号为1的记录即为每个员工的最新数据:
from django.db.models import Window, F from django.db.models.functions import RowNumber result = Employee.objects.annotate( row_rank=Window( expression=RowNumber(), partition_by=F('empid'), order_by=F('created_datetime').desc() ) ).filter(row_rank=1)
注意事项
- 如果存在同个员工同一
created_datetime下有多条记录的场景,两种方法都会返回这些重复记录,可以根据业务规则追加过滤条件,比如额外匹配最大主键值去重。 - 窗口函数方案要求数据库版本支持窗口特性:MySQL 8.0+、PostgreSQL 8.4+、SQLite 3.25+均可正常使用,如果是MySQL 5.x等不支持窗口函数的版本,使用方法1即可。
内容的提问来源于stack exchange,提问作者Akram
相关产品推荐
相关产品推荐

