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