多表查詢, 聚集查詢和分組查詢


 

 

有如下模型為例

class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) website = models.URLField() class Author(models.Model): name = models.CharField(max_length=30) class AuthorDetail(models.Model): sex = models.BooleanField(max_lenght=1, choices=((0,''),(1,''),)) email = models.EmailField() birthday = models.DateField() author = models.OneToOneField(Author, on_delete=models.CASCADE) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) publication_date = models.DateField()

 

一. 多表查詢
 
1)查詢作者的所有完整信息
注意authordetail表中沒有作者名字,名字在author表中
AuthorDetail.objects.values('sex','email','address','author__name')
author是AuthorDetail表中的外鍵字段,在外鍵后面加2個下划線跟上Author表中的name屬性,就可輸出Author表中的名字
 
如果想單獨獲得某個作者的姓名,如下
author_detail = AuthorDetail.objects.filter(email="123@qq.com")
name1 = author_detail.author.name
 
 
 
2)查詢<<我的祖國>>這本書的作者名字,出版社名字
書和作者是多對多關系
Book.objects.filter(title='我的祖國').values('authors__name')
Book.objects.filter(title='我的祖國').values('publisher__name')
 
3)查詢胡大海寫了什么書
Book.objects.filter(authors__name='胡大海').values('title')
 
4)查詢廣東人民出版社出了什么書
Book.objects.filter(publisher__name='廣東人民出版社').values('title')
 
5)查詢廣東人民出版社都有哪些作者出過書
Book.objects.filter(publisher__name='廣東人民出版社').values('author__name')
 
 
多表查詢技巧
1. 兩個下划線可生成連接查詢,查詢關聯的字段信息,可用於外鍵查詢主鍵字段信息,用objects操作
例如:book = Book.objects.filter(publisher__name='廣東人民出版社')
 
2. _set提供了對象訪問相關聯表數據的方法,使用外鍵相關模型的小寫名稱,下划線和單詞set。但是這種方法只能是關鍵類訪問外鍵類
我們有模型Publisher和Book,而Book類中我們通過外鍵關聯到了Publisher。
下面我們定義一個publisher對象表示一個出版社,就可以使用publisher.book_set的方法獲取相關聯的書籍信息了
publisher = Publisher.objects.get(name='廣東人民出版社')
publisher.book_set.all().values()
 
book.authors_set.all() 這種方法會報錯
因為authors不是Book類中的外鍵,這樣操作行不通
 
 
二. 常見的查詢方法
常見的查詢相關的API
1)get(**kwargs):返回於所有篩選條件相匹配的對象,返回結果只有一個。如果符合條件的對象超過一個,就拋出MultipleObjectsReturn異常,如果沒找到符合條件的對象,拋出DoesNotExist異常。
注意:
它返回的不是QuerySet對象,而是models的對象,比如pub=Publisher.object.get(id=1)
type(pub)返回結果為class 'hello.models.Publisher'
 
2)all(): 查詢所有結果
3)filter(**kwargs):包含與所篩選條件相匹配的對象,結果可有多個
4)exclude(**kwargs):包含那些與所選條件不匹配的對象,和filter相反
5)order_by(*fields):對查詢結果排序
6)reverse():對查詢結果反向排序
7)distinct():從返回結果中剔除重復記錄
8)values(*fields):返回一個ValuesQuerySet, 一個特殊的QuerySet子類,運行后得到的是一個可迭代的字典序列
9)values_list(*fields): 與values()功能一樣,只是返回結果是元組序列
10)count():返回數據庫中匹配查詢(QuerySet)的對象數量
11)first(): 返回第一條記錄,等價於[:1][0]
例如Publisher.objects.all().first()
12) last(): 返回最后一個記錄,等價於[::-1][0]
13) exists() :如果QuerySet包含數據,就返回True,否則返回False
例如:Publisher.objects.all().exists()
 
 

 

三.  聚集查詢和分組查詢 

先看QuerySet里的兩個函數 
1. annotate(*args,**kwargs):可以為QuerySet中的每個對象添加注解。通過計算查詢結果中的每個對象所關聯的對象集合,得到總值(也可以是平均值等),用於分組查詢
2. aggregate(*args, **kwargs): 通過對QuerySet進行計算,返回一個聚合值的字典。aggregate()中的每個參數指定一個包含在字典中的返回值。用於聚合查詢

 一些聚合函數所在位置:django.db.models,舉例如下

 

1. Avg: 返回所給字段平均值
2. Count:根據所給的關聯字段返回被關聯model的數量
3. Max: 返回所給字段的最大值
4. Min:返回所給字段的最小值
5. Sum:計算所給字段值總和
 
實例 
1. 在Book模型中增加一個price屬性
price = models.DecimalField(max_digits=5, decimal_places=2, default=10)
 
2. 查詢廣東人民出版社出了多少本書 
Publisher.objects.filter(name='廣東人民出版社').count() #注意count是小寫, 是QuerySet提供的一個方法

 

如果使用聚合函數,如下
from django.db.models import *
Publisher.objects.filter(name='廣東人民出版社').aggregate(Count('name'))
 
可以自定義個別名 
Publisher.objects.filter(name='廣東人民出版社').aggregate(mycount = Count('name'))
 
3. 查詢胡大海出的書的總價格是多少
Book.objects.filter(authors__name = '胡大海').aggregate(Sum('price'))
 
4. 查詢各作者出書的總價格是多少, 需要進行分組
Book.objects.values('authors__name').annotate(Sum('price'))
其中values()可以當做分組條件,annotate()用於分組查詢
 
5. 查詢各出版社最便宜的書價 
Book.objects.values('publisher__name').annotate(Min('price'))

 

on_delete=models.CASCADE


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM