django group by


django group by

概要

如何用 django 自带的 ORM 框架来完成 SQL 中的 group by 操作呢?

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 的组合来实现的。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM