Ano*_*tra 4 django django-models django-orm window-functions django-rest-framework
假设我们有一个模型如下
class Cake(models.Model):
baked_on = models.DateTimeField(auto_now_add=True)
cake_name = models.CharField(max_length=20)
Run Code Online (Sandbox Code Playgroud)
现在,有多个Cake是在同一天烘焙,我需要一个查询,它将返回每月蛋糕报告,其中包含每月的每一天,以及当天烘焙的第一个和最后一个蛋糕的名称.
例如,如果数据是这样的:
baked_on cake_name
11 Jan 12:30 Vanilla
11 Jan 14:30 Strawberry
11 Jan 20:45 Avocado
12 Jan 09:05 Raspberry
12 Jan 16:30 Sprinkles
12 Jan 20:11 Chocolate
Run Code Online (Sandbox Code Playgroud)
我的查询输出应该是这样的
date first last
11 Jan Vanilla Avocado
12 Jan Raspberry Chocolate
Run Code Online (Sandbox Code Playgroud)
我应该如何在单个ORM呼叫中执行此操作?
Django 2.0引入了针对这种查询的窗口函数.您的问题的简单答案将是:
Cake.objects.annotate(
first_cake=Window(
expression=FirstValue('cake_name'),
partition_by=[TruncDate('baked_on')],
order_by=F('baked_on').asc(),
),
last_cake=Window(
expression=FirstValue('cake_name'),
partition_by=[TruncDate('baked_on')],
order_by=F('baked_on').desc(),
),
day=TruncDate('baked_on'),
).distinct().values_list('day', 'first_cake', 'last_cake')
Run Code Online (Sandbox Code Playgroud)
为什么FirstValue在last_cake?这是因为默认情况下窗口查询将遍历每一行并且不会向前看,因此对于每一行,最后一行将等于当前行.使用last_row与降序排序一起将解决这个问题.或者你可以定义哪个窗口查询应该工作的框架:
Cake.objects.annotate(
first_cake=Window(
expression=FirstValue('cake_name'),
partition_by=[TruncDate('baked_on')],
order_by=F('baked_on').asc(),
),
last_cake=Window(
expression=LastValue('cake_name'),
partition_by=[TruncDate('baked_on')],
order_by=F('baked_on').asc(),
frame=ValueRange(),
),
day=TruncDate('baked_on'),
).distinct().values_list('day', 'first_cake', 'last_cake')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
603 次 |
| 最近记录: |