django group by
django group by
概要
如何用 django 自带的 ORM 框架来完成 SQL 中的 group by 操作呢?
环境介绍
foo 这个应用定义了如下模型。
class PersonModel(models.Model):
name = models.CharField('姓名', max_length=64)
age = models.PositiveIntegerField('年龄')
def __str__(self):
return f"{self.name} - {self.age}"
数据库层面看到的表结构如下。
CREATE TABLE `foo_personmodel` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
`age` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
表中的数据如下。
mysql> select * from foo_personmodel;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | tim | 16 |
| 2 | jerry | 27 |
| 3 | marry | 18 |
| 4 | tim | 20 |
| 5 | alis | 17 |
+----+-------+-----+
5 rows in set (0.00 sec)
全表聚合
一个常见的需求,查询一下表中有多少行数据。
SQL 写法。
mysql> select count(id) as counts from foo_personmodel;
+--------+
| counts |
+--------+
| 5 |
+--------+
1 row in set (0.00 sec)
ORM 实现。
from django.db.models import Count
from apps.foo.models import PersonModel
PersonModel.objects.aggregate(counts = Count(id))
{'counts': 5}
注意 aggregate 返回的不再是 queryset 而是一个字典。
values 方法
要查询出每一行 name 列的取值。
SQL 写法。
mysql> select name from foo_personmodel;
+-------+
| name |
+-------+
| tim |
| jerry |
| marry |
| tim |
| alis |
+-------+
5 rows in set (0.00 sec)
ORM 实现。
PersonModel.objects.values("name")
<QuerySet [{'name': 'tim'}, {'name': 'jerry'}, {'name': 'marry'}, {'name': 'tim'}, {'name': 'alis'}]>
django 会返回一个 queryset 并且不会去重。
分组聚合
查询同一个名字在表中出现了多少次。
SQL 写法。
mysql> select name,count(id) as counts from foo_personmodel group by name;
+-------+--------+
| name | counts |
+-------+--------+
| tim | 2 |
| jerry | 1 |
| marry | 1 |
| alis | 1 |
+-------+--------+
4 rows in set (0.00 sec)
ORM 写法。
PersonModel.objects.values("name").annotate(counts=Count(id))
<QuerySet [{'name': 'tim', 'counts': 2}, {'name': 'jerry', 'counts': 1}, {'name': 'marry', 'counts': 1}, {'name': 'alis', 'counts': 1}]>
神奇的事情发生了,当 values 和 annotate 一起使用的时候,values 就承担起了 group by 的角色。并且自动去掉了重项!
结论
django 中并没有为 group by 设置单独的方法,而是通过 values + annotate 的组合来实现的。
posted on 2020-04-09 16:58 蒋乐兴的技术随笔 阅读(10650) 评论(3) 编辑 收藏 举报