美文网首页
ORM聚合函数

ORM聚合函数

作者: 小吉头 | 来源:发表于2020-06-17 16:02 被阅读0次

表关系如下:

author
+----+--------+-----+------------+
| id | name   | age | email      |
+----+--------+-----+------------+
|  1 | 曹雪芹 |  35 | cxq@qq.com |
|  2 | 吴承恩 |  28 | wce@qq.com |
|  3 | 罗贯中 |  36 | lgz@qq.com |
|  4 | 施耐庵 |  46 | sna@qq.com |
+----+--------+-----+------------+
book
+----+----------+-------+-------+--------+-----------+--------------+----------+
| id | name     | pages | price | rating | author_id | publisher_id | remark   |
+----+----------+-------+-------+--------+-----------+--------------+----------+
|  1 | 三国演义 |   987 |   108 |    4.8 |         3 |            1 | 三国演义 |
|  2 | 水浒传   |   967 |   107 |   4.83 |         4 |            1 | 水浒传   |
|  3 | 西游记   |  1004 |   105 |   4.85 |         2 |            2 | 西游记   |
|  4 | 红楼梦   |  1007 |   109 |    4.9 |         1 |            2 | 红楼梦   |
+----+----------+-------+-------+--------+-----------+--------------+----------+
book_order
+----+-------+---------+----------------------------+
| id | price | book_id | create_time                |
+----+-------+---------+----------------------------+
|  1 |    95 |       1 | 2019-06-17 07:10:02.053000 |
|  2 |    85 |       1 | 2020-06-17 07:10:02.053000 |
|  3 |    88 |       1 | 2020-06-17 07:10:02.053000 |
|  4 |    94 |       2 | 2020-06-17 07:10:02.053000 |
|  5 |    93 |       2 | 2020-06-17 07:10:02.053000 |
+----+-------+---------+----------------------------+

平均值-AVG()

使用aggregate和annotate执行AVG():

from django.db.models import Avg
from django.db import connection
#查看所有书的平均价格
result = Book.objects.aggregate(Avg("price"))
print(result)
print(connection.queries)
>>>{'price__avg': 97.25}
>>>SELECT AVG(`book`.`price`) AS `price__avg` FROM `book`

#查看每本书的对应所有订单的平均售价
result = Book.objects.annotate(avg = Avg("bookorder__price"))
print(result)
print(connection.queries)
>>><QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>]>
>>>SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id`, AVG(`book_order`.`price`) AS `avg` FROM `book` LEFT OUTER JOIN `book_order` ON (`book`.`id` = `book_order`.`book_id`) GROUP BY `book`.`id` ORDER BY NULL LIMIT 21

相同点:
都可以执行聚合函数
不同点:
1、aggregate返回字典,示例中key默认是字段__avg,Book.objects.aggregate(avg = Avg("price"))可修改key,结果是{'avg': 97.25}
2、annotate返回QuerySet对象,使用Book.objects.annotate(avg = Avg("bookorder__price")).values()查看结果,在模型对象属性里增加了平均值属性avg

<QuerySet [{'publisher_id': 1, 'name': '三国演义', 'avg': 89.33333333333333, 'rating': 4.8, 'author_id': 3, 'pages': 987, 'price': 98.0, 'id': 1},{...},{...}]>

3、从翻译的sql可以看出,aggregate不做分组,annotate使用group by分组。默认会根据分组字段进行排序。

EXPLAIN
SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id`, AVG(`book_order`.`price`) AS `avg` FROM `book` LEFT OUTER JOIN `book_order` ON (`book`.`id` = `book_order`.`book_id`) GROUP BY `book`.`id` ORDER BY NULL LIMIT 21
>>>Extra字段 Using temporary
//去掉ORDER BY NULL查看执行计划
>>>Using temporary; Using filesort

orm翻译的sql使用了ORDER BY NULL禁用排序,提升查找效率。

数量-Count()

from django.db.models import Avg
from django.db import connection


 #book表中共有多少个出版社
result = Book.objects.aggregate(nums = Count("publisher_id"))
print(result)
print(connection.queries)
>>>{'nums': 4}
>>>SELECT COUNT(`book`.`publisher_id`) AS `nums` FROM `book`

 #book表中共有多少不重复的出版社
result = Book.objects.aggregate(nums = Count("publisher_id",distinct=True))
print(result)
print(connection.queries)
>>>{'nums': 2}
>>>SELECT COUNT(DISTINCT `book`.`publisher_id`) AS `nums` FROM `book`

#统计每本书的销量
books = Book.objects.annotate(nums = Count("bookorder__id")) //bookorder_id可以简写成bookorder
print(books.values())
print(connection.queries)
>>><QuerySet [{'pages': 987, 'publisher_id': 1, 'price': 98.0, 'id': 1, 'name': '三国演义', 'author_id': 3, 'rating': 4.8, 'nums': 3},{...},{...}]>
>>>SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id`, COUNT(`book_order`.`id`) AS `nums` FROM `book` LEFT OUTER JOIN `book_order` ON (`book`.`id` = `book_order`.`book_id`) GROUP BY `book`.`id` ORDER BY NULL LIMIT 21

最大最小值-Max()、Min()

aggregate()和annotate()可以加多个聚合函数

#author年龄最大值和最小值
result = Author.objects.aggregate(max = Max("age"),min = Min("age"))
print(result)
print(connection.queries)
>>>{'max': 46, 'min': 28}
>>>SELECT MAX(`author`.`age`) AS `max`, MIN(`author`.`age`) AS `min` FROM `author`

#获取每本书售卖时的最高价和最低价
result = Book.objects.annotate(max = Max("bookorder__price"),min = Min("bookorder__price"))
print(result.values())
print(connection.queries)
>>><QuerySet [{'publisher_id': 1, 'min': 85.0, 'max': 95.0, 'author_id': 3, 'name': '三国演义', 'id': 1, 'rating': 4.8, 'pages': 987, 'price': 98.0},{...},{...}]>
>>>SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id`, MIN(`book_order`.`price`) AS `min`, MAX(`book_order`.`price`) AS `max` FROM `book` LEFT OUTER JOIN `book_order` ON (`book`.`id` = `book_order`.`book_id`) GROUP BY `book`.`id` ORDER BY NULL LIMIT 21

求和-sum()

aggregate:

#2020年所有图书销售总额
result = BookOrder.objects.filter(create_time__year=2020).aggregate(total = Sum("price"))
print(result)
print(connection.queries)
>>>{'total': 360.0}
>>>SELECT SUM(`book_order`.`price`) AS `total` FROM `book_order` WHERE `book_order`.`create_time` BETWEEN '2019-12-31 16:00:00' AND '2020-12-31 15:59:59.999999'

因为setting里面设置了时区是Asia/Shanghai,migrations时数据库里面保存的其实是UTC时间,所以翻译结果是计算后的utc时间BETWEEN '2019-12-31 16:00:00' AND '2020-12-31 15:59:59.999999,如果要得到和数据库匹配的utc时间,可以修改setting时区为utc

TIME_ZONE = 'UTC'
USE_TZ = True

修改后sql翻译结果:BETWEEN '2020-01-01 00:00:00' AND '2020-12-31 23:59:59.999999'
annotate:

#2020年每本书的销售总额
result = Book.objects.filter(bookorder__create_time__year=2020).annotate(total=Sum("price"))
>>><QuerySet [{'name': '三国演义', 'price': 98.0, 'id': 1, 'author_id': 3, 'total': 196.0, 'publisher_id': 1, 'rating': 4.8, 'pages': 987}, {...},{...}]>
>>>SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id`, SUM(`book`.`price`) AS `total` FROM `book` INNER JOIN `book_order` ON (`book`.`id` = `book_order`.`book_id`) WHERE `book_order`.`create_time` BETWEEN '2020-01-01 00:00:00' AND '2020-12-31 23:59:59.999999' GROUP BY `book`.`id` ORDER BY NULL LIMIT 21

相关文章

  • ORM聚合函数

    表关系如下: 平均值-AVG() 使用aggregate和annotate执行AVG(): 相同点:都可以执行聚合...

  • orm FQ聚合函数自关联关系

    可以使用模型的字段A与字段B进行比较,如果A写在了等号的左边,则B出现在等号的右边,需要通过F对象构造 ;之前的查...

  • mysql子查询

    聚合函数 聚合函数对一组值执行计算,并返回单个值。 除了 COUNT 以外,聚合函数都会忽略空值。 聚合函数经常与...

  • Spark SQL原理之Aggregate实现原理

    聚合函数的分类 声明式聚合函数: 可以由Catalyst中的表达式直接构建的聚合函数,也是比较简单的聚合函数类型,...

  • sql语句

    聚合函数 分组,要和聚合函数一起用 常用聚合函数 group by xxx having xxx order by...

  • Django-数据库操作之聚合函数和排序函数

    一、聚合函数 使用aggregate()过滤器调用聚合函数,聚合函数包括:Avg平均,Count数量,Max最大,...

  • 04 - 聚合与排序

    聚合函数 聚合函数 通过 SQL 对数据进行某种操作或计算时需要使用函数。用于汇总的函数称为聚合函数或者聚集函数聚...

  • Pandas的聚合函数

    定义DataFrame 1.内置聚合函数 2.自定义聚合函数 3.字典传递给聚合函数

  • 聚合函数的进阶应用

    1.什么是聚合函数聚合函数aggregation function又称为组函数。 认情况下 聚合函数会对当前所在表...

  • Hive开窗函数

    1. 介绍 普通聚合函数聚合的行集是组,开窗函数聚合的行集是窗口。因此,普通聚合函数每组(Group by)只有一...

网友评论

      本文标题:ORM聚合函数

      本文链接:https://www.haomeiwen.com/subject/asclxktx.html