django開發系列:ORM之聚合函數

django開發系列:ORM之聚合函數

聚合函數:

  1. 所有的聚合函數都是放在django.db.models下面。

  2. 聚合函數不能夠單獨的執行,需要放在一些可以執行聚合函數的方法下面中去執行。比如aggregate。示例代碼如下:

    result = Book.objects.aggregate(Avg("price"))
    
  3. 聚合函數執行完成後,給這個聚合函數的值取個名字。取名字的規則,默認是filed+__+聚合函數名字形成的。比如以上代碼形成的名字叫做price__avg。如果不想使用默認的名字,那麼可以在使用聚合函數的時候傳遞關鍵字參數進去,參數的名字就是聚合函數執行完成的名字。實示例代碼如下:

    result = Book.objects.aggregate(avg=Avg("price"))
    

    以上傳遞了關鍵字參數avg=Avg("price"),那麼以後Avg聚合函數執行完成的名字就叫做avg

  4. aggregate:這個方法不會返回一個QuerySet對象,而是返回一個字典。這個字典中的key就是聚合函數的名字,值就是聚合函數執行後的結果。

  5. aggregateannotate的相同和不同:

    • 相同:這兩個方法都可以執行聚合函數。
    • 不同:
      • aggregate返回的是一個字典,在這個字典中存儲的是這個聚合函數執行的結果。而annotate返回的是一個QuerySet對象,並且會在查找的模型上添加一個聚合函數的屬性。
      • aggregate不會做分組,而annotate會使用group by子句進行分組,只有調用了group by子句,才能對每一條數據求聚合函數的值。
  6. Count:用來求某個數據的個數。比如要求所有圖書的數量,那麼可以使用以下代碼:

    result = Book.objects.aggregate(book_nums=Count("id"))
    

    並且Count可以傳遞distinct=True參數,用來剔除那些重複的值,只保留一個。比如要獲取作者表中,不同郵箱的個數,那麼這時候可以使用distinct=True。示例代碼如下:

    result = Author.objects.aggregate(email_nums=Count('email',distinct=True))
    
  7. MaxMin:求指定字段的最大值和最小值。示例代碼如下:

    result = Author.objects.aggregate(max=Max("age"),min=Min("age"))
    
  8. Sum:求某個字段值的總和。示例代碼如下:

    result = BookOrder.objects.aggregate(total=Sum('price'))
    

    aggregateannotate方法可以在任何的QuerySet對象上調用。因此只要是返回了QuerySet對象,那麼就可以進行鏈式調用。比如要獲取2018年度的銷售總額,那麼可以先過濾年份,再求聚合函數。示例代碼如下:

    BookOrder.objects.filter(create_time__year=2018).aggregate(total=Sum('price'))
    
  9. F表達式: 動態的獲取某個字段上的值。並且這個F表達式,不會真正的去數據庫中查詢數據,他相當於只是起一個標識的作用。比如想要將原來每本圖書的價格都在原來的基礎之上增加10元,那麼可以使用以下代碼來實現:

    from django.db.models import F
    Book.objects.update(price=F("price")+10)
    
  10. Q表達式:使用Q表達式包裹查詢條件,可以在條件之間進行多種操作。與/或非等,從而實現一些複雜的查詢操作。例子如下:

    • 查找價格大於100,並且評分達到4.85以上的圖書:
      # 不使用Q表達式的
      books = Book.objects.filter(price__gte=100,rating__gte=4.85)
      # 使用Q表達式的
      books = Book.objects.filter(Q(price__gte=100)&Q(rating__gte=4.85))
      
    • 查找價格低於100元,或者評分低於4分的圖書:
      books = Book.objects.filter(Q(price__gte=100)&Q(rating__gte=4.85))
      
    • 獲取價格大於100,並且圖書名字中不包含”傳“字的圖書:
      books = Book.objects.filter(Q(price__gte=100)&~Q(name__icontains='傳'))
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章