[实验] Django 最大值、最小值、平均值等特殊数值的数据查询

注意:

本实验是接着 《Django 自定义逻辑添加(通过自定义 save 对象实现)(一次性完成多对多表数据的插入)》而继续的

正文:

步骤一:进入相应的 Django 环境

(django_env) [root@python mysite]# python3
>>> import os,django
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
>>> django.setup()
>>> from user.models import *

步骤二:插入测试数据

>>> user = Student(sname='zhangsan',score=60,cls=Clazz(cname='Class1'))
>>> user.save()

>>> user = Student(sname='lisi',score=80,cls=Clazz(cname='Class1'))
>>> user.save()

>>> user = Student(sname='wangwu',score=90,cls=Clazz(cname='Class1'))
>>> user.save()

>>> user = Student(sname='zhaoliu',score=70,cls=Clazz(cname='Class1'))
>>> user.save()

>>> user = Student(sname='xueer',score=70,cls=Clazz(cname='Class2'))
>>> user.save()

>>> user = Student(sname='huangyi',score=70,cls=Clazz(cname='Class2'))
>>> user.save()

(补充:这里以随机插入 6 条测试数据为例)

步骤三:设置 1 个显示上 1 句 SQL 语句的函数

>>> def showsql():
...     from django.db import connection
...     print(connection.queries[-1]['sql'])

(补充:这里的 [-1] 是指显示上一条操作的 SQL 语句)

步骤四:通过聚合函数查询所需的数值

4.1 通过聚合函数查询最大值

4.1.1 导入聚合函数最大值模块
>>> from django.db.models import Max
4.1.2 通过聚合函数查询最大值(显示默认解释说明)
4.1.2.1 通过聚合函数查询最大值(显示默认解释说明)
>>> Student.objects.aggregate(Max('score'))
{'score__max': 90}


补充:
1) 这里以查询所有数据 score 字段的最大值为例
2) 这里查出的最大值是 90

4.1.2.2 显示通过聚合函数查询最大值的 SQL 语句(显示默认解释说明)
>>> showsql()
SELECT MAX(`user_student`.`score`) AS `score__max` FROM `user_student`

(补充:这里以查询所有数据 score 字段的最大值为例)

4.1.3 通过聚合函数查询最大值(显示自定义解释说明)
4.1.3.1 通过聚合函数查询最大值(显示自定义解释说明)
>>> Student.objects.aggregate(m=Max('score'))
{'m': 90}


补充:
1) 这里以查询所有数据 score 字段的最大值为例
2) 查出的最大值是 90
3) 这里显示的自定义解释说明是 m

4.1.3.2 显示通过聚合函数查询最大值的 SQL 语句(显示自定义解释说明)
>>> showsql()
SELECT MAX(`user_student`.`score`) AS `m` FROM `user_student`


补充:
1) 这里以查询所有数据 score 字段的最大值为例
2) 这里显示的自定义解释说明是 m

4.2 通过聚合函数查询最小值

4.2.1 导入聚合函数最小值模块
>>> from django.db.models import Min
4.2.2 通过聚合函数查询最小值
>>> Student.objects.aggregate(Min('score'))
{'score__min': 60}


补充:
1) 这里以查询所有数据 score 字段的最小值为例
2) 这里查出的最小值是 60

4.2.3 显示通过聚合函数查询最小值的 SQL 语句
>>> showsql()
SELECT MIN(`user_student`.`score`) AS `score__min` FROM `user_student`

(补充:这里以查询所有数据 score 字段的最小值为例)

4.3 通过聚合函数统计数据条数

4.3.1 导入聚合函数统计数据条数的模块
>>> from django.db.models import *
4.3.2 通过聚合函数统计数据条数(统计所有数据的条数)
4.3.2.1 通过聚合函数统计数据条数(统计所有数据的条数)
>>> Student.objects.aggregate(c=Count('*'))
{'c': 6}


补充:
1) 这里统计所有数据的数据总条数为例
2) 这里显示的自定义解释说明是 c
3) 这里查出的数据条数是 6

4.3.2.2 显示通过聚合函数统计数据条数的 SQL 语句(统计所有数据的条数)
>>> showsql()
SELECT COUNT(*) AS `c` FROM `user_student`


补充:
1) 这里统计所有数据的数据总条数为例
2) 这里显示的自定义解释说明是 c

4.3.3 通过聚合函数统计数据条数(统计包含某字段数据的条数)
4.3.3.1 通过聚合函数统计数据条数(统计包含某字段数据的条数)
>>> Student.objects.aggregate(c=Count('score'))
{'c': 6}


补充:
1) 这里以统计包含 score 字段的数据总条数为例
2) 这里显示的自定义解释说明是 c
3) 这里查出的数据条数是 6

4.3.3.2 显示通过聚合函数统计数据条数的 SQL 语句(统计包含某字段数据的条数)
>>> showsql()
SELECT COUNT(`user_student`.`score`) AS `c` FROM `user_student`


补充:
1) 这里以统计包含 score 字段的数据总条数为例
2) 这里显示的自定义解释说明是 c

4.4 通过聚合函数求和

4.4.1 导入聚合函数求和的模块
>>> from django.db.models import *
4.4.2 通过聚合函数求和
>>> Student.objects.aggregate(Sum('score'))
{'score__sum': 440}


补充:
1) 这里以求所有数据 score 字段的值的和为例
2) 这里求出的和是 440

4.4.3 显示通过聚合函数求和的 SQL 语句
>>> showsql()
SELECT SUM(`user_student`.`score`) AS `score__sum` FROM `user_student`

(补充:这里以求所有数据 score 字段的值的和为例)

4.5 通过聚合函数求平均数

4.5.1 导入聚合函数求平均数的模块
>>> from django.db.models import *
4.5.2 通过聚合函数求平均值
>>> Student.objects.aggregate(Avg('score'))
{'score__avg': 73.3333}


补充:
1) 这里以求所有数据 score 字段的平均值为例
2) 这里求出的平均值是 73.3333

4.5.3 显示通过聚合函数求平均值的 SQL 语句
>>> showsql()
SELECT AVG(`user_student`.`score`) AS `score__avg` FROM `user_student`

(补充:这里以求所有数据 score 字段的平均值为例)

步骤五:通过分组聚合函数查询所需的数值

5.1 导入分组聚合函数模块

>>> from django.db.models import *

5.2 通过分组聚合函数统计每组数据的条数

5.2.1 通过分组聚合函数统计每组数据的条数
>>> Student.objects.values('cls').annotate(c=Count('score'))
<QuerySet [{'cls': 1, 'c': 4}, {'cls': 2, 'c': 2}]>


补充:
1) 这里以 cls 字段进行分组,统计每组包含 score 字段数据的条数为例
2) 这里显示的自定义解释说明是 c
3) 这里求出 cls 字段值为 1 的组包含 score 字段的数据有 4 条,cls 字段的值为 2 的组包含 score 字段的数据有 2 条

5.2.2 显示通过分组聚合函数统计每组数据条数的 SQL 语句
>>> showsql()
SELECT `user_student`.`cls_id`, COUNT(`user_student`.`score`) AS `c` FROM `user_student` GROUP BY `user_student`.`cls_id` ORDER BY NULL LIMIT 21


补充:
1) 这里以 cls 字段进行分组,统计每组包含 score 字段数据的条数为例
2) 这里显示的自定义解释说明是 c

5.3 通过分组聚合函数统计求每组数据的平均值

5.3.1 通过分组聚合函数统计求每组数据的平均值
>>> Student.objects.values('cls').annotate(a=Avg('score'))
<QuerySet [{'cls': 1, 'a': 75.0}, {'cls': 2, 'a': 70.0}]>


补充:
1) 这里以 cls 字段进行分组,求每组数据 score 字段的平均值为例
2) 这里显示的自定义解释说明是 a
3) 这里求出 cls 字段值为 1 的组 score 字段的平均值为 75.0,cls 字段的值为 2 的组 score 字段的平均值为 70.0

5.3.2 显示通过分组聚合函数统计求每组数据的平均值的 SQL 语句
>>> showsql()
SELECT `user_student`.`cls_id`, AVG(`user_student`.`score`) AS `a` FROM `user_student` GROUP BY `user_student`.`cls_id` ORDER BY NULL LIMIT 21


补充:
1) 这里以 cls 字段进行分组,求每组数据 score 字段的平均值为例
2) 这里显示的自定义解释说明是 a

步骤六:通过子查询查询所需的数值

6.1 导入子查询模块

>>> from django.db.models import *

6.2 通过子查询查询总值最大的 1 组数据的总值

6.2.1 通过子查询查询总值最大的 1 组数据的总值
>>> Student.objects.values('cls').annotate(s=Sum('score')).aggregate(m=Max('s'))
{'m': 300}


补充:
1) 这里以 cls 字段进行分组,求每组数据 score 字段的总值,再将其求和为例
2) 这里显示的自定义解释说明是 m
3) 这里求出 score 字段的总值为 300
4) values 和 annotate 一起使用时 values 则发挥的是 group by 的作用
5) values 单独使用时 values 发挥的是部分查询的作用

6.2.2 显示通过子查询查询总值最大的 1 组数据总值的 SQL 语句
>>> showsql()
SELECT MAX(`s`) FROM (SELECT `user_student`.`cls_id` AS Col1, SUM(`user_student`.`score`) AS `s` FROM `user_student` GROUP BY `user_student`.`cls_id` ORDER BY NULL) subquery


补充:
1) 这里以 cls 字段进行分组,求每组数据 score 字段的总值,再将其求和为例
2) 这里显示的自定义解释说明是 m
3) values 和 annotate 一起使用时 values 则发挥的是 group by 的作用
4) values 单独使用时 values 发挥的是部分查询的作用

步骤七:通过关联查询查询所需的数值

7.1 导入关联查询模块

>>> from django.db.models import *

7.2 通过关联查询查询关联的数据

7.2.1 通过关联查询查询关联的数据(查询数据表中的非外键字段)
7.2.1.1 通过关联查询查询关联的数据(查询数据表中的非外键字段)
>>> Student.objects.values('cls__cname')
<QuerySet [{'cls__cname': 'Class1'}, {'cls__cname': 'Class1'}, {'cls__cname': 'Class1'}, {'cls__cname': 'Class1'}, {'cls__cname': 'Class2'}, {'cls__cname': 'Class2'}]>


补充:
1) 这里查出了 4 条 cls__cname 为 Class1 的数据和 2 条 cls__cname 为 Class 2 的数据
2) 这里的 cls 是 Django 数据模型类中两张数据表的外键字段,但是 cname 并不是数据库中两张数据表的外键字段

7.2.1.2 通过关联查询查询关联数据的 SQL 语句(查询数据表中的非外键字段)
>>> showsql()
SELECT `user_clazz`.`cname` FROM `user_student` INNER JOIN `user_clazz` ON (`user_student`.`cls_id` = `user_clazz`.`id`) LIMIT 21

(补充:这里的 cls_id 是 user_student 表中关联 user_clazz 表中 id 字段的外键字段)

7.2.2 通过关联查询查询关联的数据(查询数据表中的外键字段)
7.2.2.1 通过关联查询查询关联的数据(查询数据表中的外键字段)
>>> Student.objects.values('cls__id')
<QuerySet [{'cls__id': 1}, {'cls__id': 1}, {'cls__id': 1}, {'cls__id': 1}, {'cls__id': 2}, {'cls__id': 2}]>


补充:
1) 这里查出了 4 条 cls__id 为 1 的数据和 2 条 cls__id 为 2 的数据
2) 这里的 cls 是 Django 数据模型类中两张数据表的外键字段,并且 id 也是数据库中两张数据表的外键字段

7.2.2.2 通过关联查询查询关联数据的 SQL 语句(查询数据表中的外键字段)
>>> showsql()
SELECT `user_student`.`cls_id` FROM `user_student` LIMIT 21

(补充:这里的 cls_id 是 user_student 表中关联 user_clazz 表中 id 字段的外键字段)

步骤八:退出相应的 Django 环境

>>> quit()

步骤九:Django 聚合函数查询、分组聚合函数查询、子查询、关联查询的总结

1) 单独用 aggregate 则代表单独使用聚合函数
2) 单独用 annotate 则代表单独使用分组聚合函数
3) 在 annotate 前面加上 values 则是指定某一个字段进行分组,values.annotate