【Django】聚合查询——聚合和其他 QuerySet 子句(filter() 、 exclude()、order_by()、values())

当使用复杂的ORM方式查询时,如果有困惑,使用 str(queryset.query) 查看对应生成的SQL语句。

聚合和其他 QuerySet 子句

filter() 和 exclude()

聚合结果也可以使用过滤。任何应用于普通模型字段的 filter() (或 exclude())对聚合的对象也有约束效果。

当与 annotate() 子句一起使用时,过滤器的效果是限制用来计算“注释”( annotate() 子句会给queryset中的对象增加一个属性和值,称之为“注释”)的对象。

例如,以下查询生成所有标题以 “Django” 开头的书籍的带注释列表:

>>> from django.db.models import Avg, Count
>>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count("authors"))

当与 aggregate() 子句一起使用时,过滤器的效果是限制用来计算聚合的对象。

例如,以下查询生成所有标题以 “Django” 开头的书籍的平均价格:

>>> Book.objects.filter(name__startswith="Django").aggregate(Avg("price"))

过滤注释

注解过的值也可以使用过滤器。注解的别名可以和任何其他模型字段一样使用 filter()exclude()子句。(因为使用 annotate()生成的也是一个QuerySet,根据链式查询的规则,是可以这样的。)
例如,要生成一个具有多位作者的书籍列表:

>>> Book.objects.annotate(num_authors=Count("authors")).filter(num_authors__gt=1)

annotate() 和 filter() 子句的顺序

当开发一个涉及 annotate()filter() 子句的复杂查询时,要特别注意应用于 QuerySet 的子句的顺序。

当一个 annotate() 子句应用于查询,会根据查询状态来计算注释。这实际上意味着 filter()annotate() 不是可交换的操作。

filter()用在前面,会先过滤对象,再生成注释。
annotate()用在前面,会先生成注释,然后过滤对象,在多对多的查询和一对多的反向查询时,会容易观察到差异。例如:

  • 出版者A有两本评分4和5的书。
  • 出版者B有两本评分1和4的书。
  • 出版者C有一本评分1的书。
    以下是一个使用 Count 聚合的示例:
>>> a, b = Publisher.objects.annotate(avg_rating=Avg("book__rating")).filter(
...     book__rating__gt=3.0
... )
>>> a, a.avg_rating
(<Publisher: A>, 4.5)  # (5+4)/2
>>> b, b.avg_rating
(<Publisher: B>, 2.5)  # (1+4)/2>>> a, b = Publisher.objects.filter(book__rating__gt=3.0).annotate(
...     avg_rating=Avg("book__rating")
... )
>>> a, a.avg_rating
(<Publisher: A>, 4.5)  # (5+4)/2
>>> b, b.avg_rating
(<Publisher: B>, 4.0)  # 4/1 (book with rating 1 excluded)

第一个查询请求至少有一本评分3以上的书籍的出版者的书籍平均分。第二个查询只请求评分3以上的作者书籍的平均评分。

order_by()

annotate() 子句之后可以用order_by()排序,因为注释相当于查询对象结果的一个属性了。
例如,要按参与书籍创作的作者数量对书籍的 QuerySet 进行排序:

>>> Book.objects.annotate(num_authors=Count("authors")).order_by("num_authors")

values()

通常,注解值会添加到每个对象上,即一个被注解的 QuerySet 将会为初始 QuerySet 的每个对象返回一个结果集。然而,当使用 values() 子句来对结果集进行约束时,生成注解值的方法会稍有不同。不是在原始 QuerySet 中对每个对象添加注解并返回,而是根据定义在 values() 子句中的字段组合先对结果进行分组,再对每个单独的分组进行注解,这个注解值是根据分组中所有的对象计算得到的。
通过一个例子对比一下:
查询每个作者所著书的平均评分:

>>> Author.objects.annotate(average_rating=Avg("book__rating"))

使用了values("name")

Author.objects.values("name").annotate(average_rating=Avg("book__rating"))

在这个例子中,作者会按名字分组,所以你只能得到不重名的作者分组后计算出的注释值。如果数据中有两个作者同名,那么他们原本各自的查询结果将被合并到同一个结果中;两个作者的所有评分都将被计算为一个平均分。

annotate() 和 values() 的顺序

和使用 filter() 一样,作用于某个查询的 annotate()values() 子句的顺序非常重要。如果 values() 子句在 annotate() 之前,就会根据 values() 子句产生的分组来计算注解。

然而如果 annotate() 子句在 values() 之前,就会根据整个查询集生成注解。然后 values() 子句只能限制输出的字段。例如:

>>> Author.objects.annotate(average_rating=Avg("book__rating")).values(
...     "name", "average_rating"
... )

这段代码将为每个作者添加一个唯一注释,但只有作者姓名和 average_rating 注释会返回在输出结果中。

和 order_by() 一起用会发生化学反应

这里需要注意的一点是order_by()会影响分组。

聚合所生成的注释

你也可以在生成的注释结果上生成聚合。例如,如果您想计算每本书的平均作者数量,您首先要用作者数量对书籍集进行注释,然后对该作者数量进行聚合:

>>> from django.db.models import Avg, Count
>>> Book.objects.annotate(num_authors=Count("authors")).aggregate(Avg("num_authors"))
{'num_authors__avg': 1.66}

在空查询集或组上进行聚合操作时,需要格外小心,因为这可能会导致未定义的行为或错误。在执行聚合操作之前,通常应确保查询集或组中包含足够的数据以执行所需的聚合计算。如果查询集或组为空,可以使用条件语句来避免聚合错误或不必要的操作。

当对空的查询集或分组应用聚合操作时,结果通常默认为其 default 参数,通常是 None。这种行为发生是因为当执行的查询不返回任何行时,聚合函数会返回 NULL。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/723065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 HBase Phoenix 构建实时数仓(1)—— Hadoop HA 安装部署

目录 一、主机规划 二、环境准备 1. 启动 NTP 时钟同步 2. 修改 hosts 文件 3. 配置所有主机间 ssh 免密 4. 修改用户可打开文件数与进程数&#xff08;可选&#xff09; 三、安装 JDK 四、安装部署 Zookeeper 集群 1. 解压、配置环境变量 2. 创建配置文件 3. 创建新…

vite、mode如果为production打包后 .env.production 中 VITE_API_DOMAIN变量作为API地址吗

Vite 是一个现代化的前端构建工具&#xff0c;它使用 .env 文件来管理不同环境下的环境变量。通过为不同的环境&#xff08;如开发环境、生产环境等&#xff09;设置不同的 .env 文件&#xff0c;你可以控制这些环境中的变量&#xff0c;这些变量在构建时会被注入到项目中 当你…

382. K取方格数(图论,费用流,拆点,上下界可行流,网格图模型)

在一个 NN 的矩形网格中&#xff0c;每个格子里都写着一个非负整数。 可以从左上角到右下角安排 K 条路线&#xff0c;每一步只能往下或往右&#xff0c;沿途经过的格子中的整数会被取走。 若多条路线重复经过一个格子&#xff0c;只取一次。 求能取得的整数的和最大是多少。…

qsort函数实现

&#xff08;一篇学习代码&#xff09; 仿照qsort函数的功能&#xff0c;实现冒泡排序 #include<stdio.h> #include<string.h> //qsort函数实现 // //如果指针p1指向的值大于指针p2指向的值&#xff0c;则返回值大于0&#xff0c; // 相等&#xff0c;返回0&am…

mac电脑版MATLAB R2023b for Mac中文激活版

MATLAB R2023b for Mac&#xff1a;科学计算的终极工具 软件下载&#xff1a;MATLAB R2023b for Mac中文激活版下载 &#x1f52c; 探索科学&#xff0c;无限可能 MATLAB R2023b for Mac&#xff0c;助您深入挖掘科学计算的奥秘。从数据分析、算法设计到可视化展示&#xff0c;…

WPF依赖属性概述

文章目录 一、前言二、依赖属性2.1 前置知识2.2 依赖属性与CLR属性2.3 依赖属性支持CLR属性2.4 设置属性值2.4.1 在XAML中设置属性值2.4.2 在代码中设置属性 2.5 依赖属性提供的属性功能2.5.1 资源2.5.2 数据绑定2.5.3 样式2.5.4 动画2.5.5 元数据覆盖2.5.6 属性值继承2.5.7 WP…

基于GitBucket的Hook构建ES检索PDF等文档全栈方案

背景 之前已简单使用ES及Kibana和在线转Base64工具实现了检索文档的demo&#xff0c;预期建设方案是使用触发器类型从公共的文档源拉取最新的文件&#xff0c;然后调用Java将文件转Base64后入ES建索引&#xff0c;再提供封装接口给前端做查询之用。 由于全部内容过长&#xff…

YOLO算法改进Backbone系列之:RepViT

摘要&#xff1a;近年来&#xff0c;与轻量级卷积神经网络(cnn)相比&#xff0c;轻量级视觉变压器(ViTs)在资源受限的移动设备上表现出了更高的性能和更低的延迟。这种改进通常归功于多头自注意模块&#xff0c;它使模型能够学习全局表示。然而&#xff0c;轻量级vit和轻量级cn…

《操作系统真相还原》读书笔记四:安装nasm

下载链接&#xff1a;https://www.nasm.us/pub/nasm/releasebuilds/2.13.03/ 下载-解压-安装 tar zxvf nasm-2.13.03.tar.gz ./configure --prefix/home/truthos/nasm/toolchain/make && makeinstall执行make install export PATH/home/truthos/nasm/toolchain/bin:…

微信小程序云开发教程——墨刀原型工具入门(编辑页面)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

硬件工程师面经整理20_阻抗匹配

文章目录 阻抗匹配_微波电路/低噪放/差分信号线1 微波电路的匹配电阻2 低噪声运放阻抗匹配3 差分信号线阻抗匹配一般是多少 互连链路阻抗特性 阻抗匹配_微波电路/低噪放/差分信号线 1 微波电路的匹配电阻 微波电路的匹配电阻指的是在微波频段内&#xff0c;由于电路阻抗的不匹…

html标签之表格标签,资料分享

二.准备工作 与中国大部分在校生一样&#xff0c;从不考虑多多参加社会活动为自己铺路&#xff0c;直到找工作时才发现自己一无所有。 是的&#xff0c;一无所有。对于求职来说&#xff0c;如果不找对口工作&#xff0c;那么你的专业知识已经无用武之地。能证明你能力的实践活…

Windows上websocket客户端连接定时存储消息到文件并加载文件定时发送服务端工具实现

场景 在业务开发中&#xff0c;需要对接三方websocket协议数据或者连接并存储线上websocket协议数据&#xff0c;需要使用websocket客户端 连接线上的websocket服务端获取并存储数据&#xff0c;然后将数据存储成文件格式可移植&#xff0c;并将数据复制 到本地&#xff0c;…

MATLAB知识点:while循环的注意事项

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自​第4章&#xff1a;MATLAB程序流程控制 在使用while循…

Linux中basename作用

在Shell脚本中&#xff0c;basename 是一个用于提取文件名或路径的基本名称&#xff08;basename&#xff09;的工具。它通常用于处理文件路径&#xff0c;以获取文件的名称部分或去除路径信息。 basename 命令的语法如下&#xff1a; basename STRING [SUFFIX] 其中&#x…

docker 安装rabbitmq并配置hyperf使用

这里我想完成的是 制作消息&#xff08;多个协程制造&#xff09;——》推送到rabbitmq——》订阅消息队列——》消费消息&#xff08;ws协程客户端【一次消费多条】/ws前端&#xff09; 利用 WebSocket 协议让客户端和服务器端保持有状态的长链接&#xff0c;保存链接上来的客…

Grind 75 | 1. Two Sum | 2. valid parentheses

来刷刷Grind 75, Blind 75作者更新版. Leetcode1 两数之和 经典题 link 思路&#xff1a; 很明显用hash table&#xff0c;一开始思考遍历2遍数组&#xff0c;第一遍加入hash table中&#xff0c; 第二遍对每个元素看能不能找到sum target&#xff0c;但思考如果有重复元素…

阿里云2核4G服务器支持多少人同时在线?

2核4G服务器支持多少人在线&#xff1f;阿里云服务器网账号下的2核4G服务器支持20人同时在线访问&#xff0c;然而应用不同、类型不同、程序效率不同实际并发数也不同&#xff0c;2核4G服务器的在线访问人数取决于多个变量因素&#xff1a; 2核4G&#xff1a;2核CPU和4G内存对…

学习笔记-cmake

cmake的版本号说明&#xff1a; CMAKE_MINIMUM_REQUIRED(VERSION 3.10) # 指定编译 C 版本 set(CMAKE_CXX_STANDARD 17) 创建一个工程&#xff1a; project(preprocess) 工程下创建一个项目&#xff1a; SET(PROGRAM WorkStation) include路径&#xff1a; set (INCLUD…

Nginx原理以及基础知识详解

Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;具有高并发性、高可靠性、低内存消耗等特点。其工作原理和基础知识如下&#xff1a; 一、Nginx的工作原理 Nginx采用多进程模型&#xff0c;主进程负责接收客户端的连接请求&#xff0c;然后将连接请求分发给工作进程来处…