2015年5月7日 星期四

aggregate() vs annotate()

Django Model的aggregate()和annotate()
如同SQL的group by,可以輕易地計算欄位並且運用。


aggregate() 和 annotate()差別


from django.db.models import Avg, Max, Min

Book.objects.all().aggregate(Avg('price'))

>> {'price__avg': 134.35}

Book.objects.all().annotate(Avg('price'))

>>[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]

進一步來看annotate()
Book.objects.all().annotate(Avg('price')).values()
>>[{'book_name':'Amy' , 'price__avg':100 , 'price':100} , ...]


annotate是每一筆資料個別算平均,回傳QuerySet型態。  
aggregate是所有資料一起算平均,並且回傳dictionary型態。
(所以aggregate後面不能使用model用法 (例如:filter)。)

同時算多筆不同的集合
Book.objects.all().annotate(Avg('price'), Max('price'), Min('price'))
Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))



重新命名欄位名稱


Book.objects.aggregate(Avg('price'))
新的欄位名稱為price__Avg(原本欄位__查詢型態)

像SQL "as" 的語法可以重新命名
Book.objects.aggregate(PriceAvg=Avg('price'))
新的欄位名稱為PriceAvg的欄位平均值



Group by 欄位
使用values()搭配annotate()
不過有個限制是,只能group by一個欄位

values() : 可以取出特定的欄位並也回傳dictionary型態

Book.objects.all().values('book_name','price')
>>[{'book_name':'book1' , 'price':200} , ...]

如果要將相同的book_name Group by
Book.objects.all().values('book_name').annotate(group_cnt=Count('book_name'))
>>[{'book_name' : 'book1' , 'group_cnt':2} , ...]
(group_cnt:找到兩筆一樣名稱的book_name)




沒有留言:

張貼留言