本文目录导读:

是的,Django ORM 从 Django 3.2 开始支持窗口函数,具体支持情况如下:
版本支持情况
- Django 3.2+:支持基本的窗口函数功能
- Django 4.0+:增加更多窗口函数和功能
- Django 5.0+:进一步增强了窗口函数的能力
主要支持的窗口函数
排名函数
from django.db.models import Window
from django.db.models.functions import Rank, DenseRank, RowNumber, NTile
# 行号
MyModel.objects.annotate(
row_num=Window(expression=RowNumber(), order_by='-created_at')
)
# 排名(允许并列,有间隙)
MyModel.objects.annotate(
rank=Window(expression=Rank(), order_by='-score')
)
# 密集排名(允许并列,无间隙)
MyModel.objects.annotate(
dense_rank=Window(expression=DenseRank(), order_by='-score')
)
# 分桶
MyModel.objects.annotate(
ntile=Window(expression=NTile(4), order_by='-score')
)
偏移函数
from django.db.models.functions import Lag, Lead, FirstValue, LastValue
# 前一行
MyModel.objects.annotate(
prev_score=Window(expression=Lag('score'), order_by='created_at')
)
# 后一行
MyModel.objects.annotate(
next_score=Window(expression=Lead('score'), order_by='created_at')
)
# 第一个值
MyModel.objects.annotate(
first=Window(expression=FirstValue('score'),
partition_by='category',
order_by='created_at')
)
# 最后一个值
MyModel.objects.annotate(
last=Window(expression=LastValue('score'),
partition_by='category',
order_by='created_at')
)
聚合函数作为窗口函数
from django.db.models import Sum, Avg, Count, Max, Min
# 累计求和
MyModel.objects.annotate(
running_total=Window(
expression=Sum('amount'),
order_by='created_at'
)
)
# 分区平均值
MyModel.objects.annotate(
category_avg=Window(
expression=Avg('score'),
partition_by='category'
)
)
# 分区内的最大值
MyModel.objects.annotate(
category_max=Window(
expression=Max('score'),
partition_by='category'
)
)
实际使用示例
示例1:计算累计总和
from django.db.models import Window, F
from django.db.models.functions import Sum
# 按部门分组,计算员工薪资的累计和
Employee.objects.annotate(
running_salary=Window(
expression=Sum('salary'),
partition_by=['department'],
order_by=['hire_date']
)
)
示例2:计算移动平均
from django.db.models import Window, Avg
from django.db.models.functions import RowNumber
# 3期移动平均
Sales.objects.annotate(
moving_avg=Window(
expression=Avg('amount'),
order_by='date',
frame=Window.ROWS(
start=-2, # 前2行
end=0 # 当前行
)
)
)
示例3:分区计算排名
# 按部门分区,按薪资排名
Employee.objects.annotate(
salary_rank=Window(
expression=Rank(),
partition_by=['department'],
order_by=F('salary').desc()
)
)
注意事项
-
数据库兼容性:窗口函数依赖于数据库支持,不同数据库的兼容性:
- PostgreSQL:全面支持
- MySQL 8.0+:大多数支持
- SQLite 3.25+:基本支持
- Oracle:全面支持
-
框架限制:窗口函数的
frame目前只支持ROWS模式,不支持RANGE或GROUPS -
性能考虑:窗口函数可能对数据库性能有影响,建议在大数据集上使用时注意优化
替代方案(如果数据库不支持)
# 使用子查询模拟窗口函数
from django.db.models import Subquery, OuterRef
rank_subquery = Employee.objects.filter(
department=OuterRef('department'),
salary__gte=OuterRef('salary')
).annotate(
count=Count('id')
).values('count')[:1]
Employee.objects.annotate(
salary_rank=Subquery(rank_subquery)
)
Django的窗口函数功能已经相当完善,可以满足大多数分析查询需求,如果你的数据库版本支持,推荐直接使用原生的窗口函数,性能更好,代码也更简洁。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播