聚合函數與F/Q表達式

聚合函數 取名: field + __ + 聚合函數名字 ,如:price__avg;可傳關鍵字參數修更名字:avg=Avg("price");sql

aggregate:不會返回一個 QuerySet 對象,而是返回一個字典,key爲聚合函數的名字,value爲聚合函數執行結果;數據庫

annotate:返回一個 QuerySet 對象;django

相同點:函數

  1. 均可執行聚合函數;可在任何的‘QuerySet’對象上調用,所以只要返回了‘QuerySet’對象,便可進行鏈式調用,如 index5 中獲取年度銷售總額,可先過濾年份再求聚合函數;

不一樣點:spa

  1.  aggregate 返回一個字典,字典中存儲聚合函數執行的結果;而 annotate 返回一個 QuerySet對象 ,並在查找的模型上添加一個聚合函數的屬性;
  2.  aggregate 不會作分組,而 annotate 會使用 Group by 字句進行分組,只有調用該字句才能對每一條數據求聚合函數的值;
  • 數據庫中的內容

 

  • models.py文件:
     1 from django.db import models
     2 
     3 class Author(models.Model):
     4     '''做者模型'''
     5     name = models.CharField(max_length=100)
     6     age = models.IntegerField()
     7     email = models.EmailField()
     8 
     9     class Meta:
    10         db_table = 'author'
    11 
    12 class Publisher(models.Model):
    13     '''出版社模型'''
    14     name = models.CharField(max_length=300)
    15 
    16     class Meta:
    17         db_table = 'publisher'
    18 
    19 class Book(models.Model):
    20     '''圖書模型'''
    21     name = models.CharField(max_length=300)
    22     pages = models.IntegerField()
    23     price = models.FloatField()
    24     rating = models.FloatField()
    25     author = models.ForeignKey(Author,on_delete=models.CASCADE)
    26     publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE)
    27 
    28     class Meta:
    29         db_table = 'book'
    30 
    31 class Bookorder(models.Model):
    32     '''圖示訂單模型'''
    33     book = models.ForeignKey('Book',on_delete=models.CASCADE)
    34     price = models.FloatField()
    35     create_time = models.DateTimeField(auto_now_add=True,null=True)
    36 
    37     class Meta:
    38         db_table = 'book_order'

     

  • views.py文件:
     1 from django.shortcuts import render
     2 from django.http import HttpResponse
     3 from .models import Author,Publisher,Book,Bookorder
     4 from django.db.models import Avg,Count,Max,Min,Sum
     5 from django.db import connection
     6 
     7 def index(request):
     8     # 獲取全部圖書訂價的平均價(使用aggregate);Avg:平均值;
     9     result = Book.objects.aggregate(Avg('price'))
    10     print(result)
    11     print(connection.queries)
    12     return HttpResponse('index')
    13     # >>>{'price__avg': 97.25}
    14     # >>>{'price__avg': 97.25}
    15     # {'sql': 'SELECT AVG(`book`.`price`) AS `price__avg` FROM `book`';
    16 
    17 def index2(requset):
    18     # 獲取每一本銷售的平均價格(使用annotate);
    19     books = Book.objects.annotate(avg=Avg('bookorder__price'))
    20     for book in books:
    21         print("%s:%s" % (book.name,book.avg))
    22     print(connection.queries)
    23     return HttpResponse('index2')
    24     #三國演義:89.33333333333333
    25     # 水滸傳:93.5
    26     # 西遊記:None
    27     # 紅樓夢:None
    28     # `book_order` ON (`book`.`id` = `book_order`.`book_id`) GROUP BY `book`.`id` ORDER BY NULL';
    29 
    30 def index3(request):
    31     # book 表中總共有多少本書;
    32     # Count:求某個數據的的個數;
    33     result = Book.objects.aggregate(nums=Count('id'))
    34     # author 表中總共有多少個不一樣的郵箱;
    35     # 使用‘distinct=True’剔除重複的值;
    36     results = Author.objects.aggregate(book_num=Count('email',distinct=True))
    37     
    38     # 統計每本書的銷量
    39     books = Book.objects.annotate(book_nums=Count('bookorder'))
    40     for book in books:
    41         print("%s:%s" % (book.name,book.book_nums))
    42     print(books)
    43     print(connection.queries)
    44     return HttpResponse("index3")
    45     # 三國演義:3
    46     # 水滸傳:2
    47     # 西遊記:0
    48     # 紅樓夢:0
    49 
    50 
    51 def index4(request):
    52     result = Author.objects.aggregate(max=Max('age'),min=Min('age'))
    53     # 每本圖書售賣前的最大及最小价格;
    54     books = Book.objects.annotate(max=Max("bookorder__price"),min=Min("bookorder__price"))
    55     for book in books:
    56         print("%s:%s:%s" % (book.name,book.max,book.min))
    57     print(connection.queries)
    58     return HttpResponse("index4")
    59 
    60     # 三國演義:95.0:85.0
    61     # 水滸傳:94.0:93.0
    62     # 西遊記:None:None
    63     # 紅樓夢:None:None
    64 
    65 
    66 def index5(request):
    67     # 求全部圖書的銷售總額;
    68     result = Book.objects.aggregate(total=Sum("price"))
    69     print(result)
    70     print(connection.queries)
    71     # {'total': 389.0}
    72     # {'sql': 'SELECT SUM(`book`.`price`) AS `total` FROM `book`', 'time': '0.001'};
    73 
    74     # 求每一本圖書的銷售總額;
    75     books = Book.objects.annotate(total=Sum('bookorder__price'))
    76     for book in books:
    77         print("%s:%s" % (book.name,book.total))
    78     print(connection.queries)
    79     # 三國演義: 268.0
    80     # 水滸傳: 187.0
    81     # 西遊記: None
    82     # 紅樓夢: None
    83     
    84 
    85     # 求2018年度的銷售總額;
    86     result = Bookorder.objects.filter(create_time__year=2019).aggregate(total=Sum("price"))
    87     # 求2018年度每一本圖書的銷售總額;
    88     books = Book.objects.filter(bookorder__create_time__year=2019).annotate(total=Sum("bookorder__price"))
    89     for book in books:
    90         print("%s:%s" % (book.name,book.total)  )
    91     print(connection.queries)
    92     # 三國演義: 268.0
    93     # 水滸傳: 187.0
    94     # `book_order`.`create_time` BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 23:59:59.999999' GROUP BY `book`.`id`

     

 

  • F表達式:動態獲取某個字段上的值,不會真正到數據庫中查詢數據,只起一個標識的做用;
     1 def index6(requset):
     2     # 給每本書售價增長10元;update;
     3     Book.objects.update(price=F('price')+10)
     4     print(connection.queries[-1])
     5     # 'UPDATE `book` SET `price` = (`book`.`price` + 10)';
     6 
     7     # Author中name與email相同的內容;
     8     authors = Author.objects.filter(name=F('emile'))
     9     for author in authors:
    10         print("%s:%s" % (author.name,author.email))
    11     return HttpResponse('index6')

     

  • Q表達式:包裹查詢條件,可在條件間進行多種操做:與 & 、或 | 、非 ~  等查詢操做;
     1 def index7(requset):
     2     # 一、獲取價格大於100,評分大於4.5的圖書;
     3     # books = Book.objects.filter(price__gte=100,rating=4.5)
     4     books = Book.objects.filter(Q(price__gte=100)&Q(rating__gte=4.5))
     5     for book in books:
     6         print("%s:%s:%s" % (book.name,book.price,book.rating))
     7         
     8     ---
     9 
    10     # 二、獲取價格低於100,或者評分低於4.5分的圖書;
    11     books = Book.objects.filter(Q(price__lt=100)|Q(rating__lt=4.5))
    12     for book in books:
    13         print("%s:%s:%s" % (book.name,book.price,book.rating))
    14        
    15     ---
    16  
    17     # 三、獲取價格大於100,而且圖書名字不包含「傳」字的圖書;
    18     books = Book.objects.filter(Q(price__gte=100)&~Q(name__icontains=''))
    19     for book in books:
    20         print("%s:%s:%s" % (book.name,book.price,book.rating))
    21     return HttpResponse('index7')
相關文章
相關標籤/搜索