django-orm聚合查询与分组查询-FQ查询

常见的聚合函数有:  sum avg min max count

聚合函数可以单独使用,不一定要和分组配合使用:只不过聚合函数与group by搭配使用

统计每个部门有多少人:
原生sql:select count(name) from emp;
引入聚合函数
from django.db.models import Avg,Count,Sum,Min,Max
orm:
models.Book.objects.all().aggregate(Avg(
"price"))
结果为:{'price__sum':'2158.00'}
也可以自定义key,相当于sql中的as别名
models.Book.objects.all().aggregate(avgprice=Avg("price"))
结果为:{'avgprice':'2158.00'}

注意aggregate返回结果是个字典,是queryset的终止语句。(查询api返回结果都是queryset所以能一直点 "." 下去。

#统计每一本书的作者个数
select book.id ,book.title,count(1) from book join bookAuthor on book,id=bookAuthor.book_id group by book.id,book.title;
models.Book.objects.all().annotate(Count("authors"))

#统计每一本书的价格,annotate返回结果queryset
#all可以得出[book_obj1,book_obj2,book_obj3]annotate对每一组进行统计,统计每组price的和
ret=models.Book.objects.all().annotate(c=sum("price"))
for obj in ret:
    print(obj.title,obj.c)
#查询每一个出版社出版过的所有书籍的总价格
models.Publish.objects.all().annotate(Sum("bookList__price"))
方式二:values相当于group by分组条件,annotate会将重复对象合并为一个组,
models.Book.objects.all().values("publisher__name").annotate(Sum("price"))

 

FQ查询

我们给book表添加俩个字段comment_num评论数,read_num阅读数

F查询
引入 from django.db.models import F,Q
#
查询评论大于50的书 models.Book.objects.filter(comment_um__gt=50) #查询评论数大于阅读数的书,当等于后面为一个变量时使用F获取变量的值 models.Book.objects.filter(comment_num__gt=F("read_num")) #为所有的书提高十块钱 models.Book.objects.all().update(price=F("price")+10)

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),
你可以使用Q 对象。
Q 对象可以使用& 和| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象
Q查询,| & ~(反)

#查询评论数大于50或者阅读数大于50的书,并且价格小于100
models.Book.objects.filter(Q(Q(comment_num__gt=50)|Q(read_num__gt=50))&Q(price__lt=100))

注意:如果出现Q 对象,它必须位于所有关键字参数的前面

错误使用方法

models.Book.objects.filter(price__lt=100,Q(comment_num__gt=10)|Q(read_num__lt=100))
#这是错误的写法,price__lt=100必须放在条件的最后面

 

##总结

nodels.py: 

class Book(models.Model):

    nid=models.AutoField(primary_key=True)
    title=models.CharField(max_length=32)
   
    # 书籍与出版社: 一对多
    publisher=models.ForeignKey(to="Publish",related_name="bookList")

    # 书籍与作者: 多对多
    authors=models.ManyToManyField("Author")


class Publish(models.Model):

    name=models.CharField(max_length=32)
   
class Author(models.Model):
    name=models.CharField(max_length=32)
    
class AuthorDetail(models.Model):

    addr=models.CharField(max_length=32)
    author=models.OneToOneField("Author")

    
    
1、单表查询

       models.Book.obejcts.all()       #   QuerySet    []        
       models.Book.obejcts.filter(nid__gt=1,nid__lt=10)  #   QuerySet   []             
       models.Book.obejcts.get()       # model对象   
       models.Book.obejcts.values()     #   QuerySet   [{},{}]            
       models.Book.obejcts.values_list()      
       models.Book.obejcts.exclude()      
       models.Book.obejcts.all().first()   
       models.Book.obejcts.all().last()   
       models.Book.obejcts.all().orderby()   
       models.Book.obejcts.all().reverse() 
       models.Book.obejcts.values("price").distinct() 
       models.Book.obejcts.all().count()
       models.Book.obejcts.all().exist()   
       
       ---- 双下划线:
        models.Book.obejcts.filter(nid__gt=12)    
        models.Book.obejcts.filter(price__in=[112,223,444])    
       
    支持链式操作:   
         models.Book.obejcts.all().filter().orderby("id").count() 
         models.Book.obejcts.all().get().orderby("id").count() 
         
1、跨表查询

   ----  基于对象
   
         (1) 查询Linux这本书的出版社名称和作者名字   属于正向查询  按关联字段
             book_obj=models.Book.obejcts.get(title="linux")
             book_obj.publisher.name
             
             authors_list=book_obj.authors.all()
             for author in authors_list:
                 print(author.name)    
         
         (2) 人民出版社出版过的所有书籍名称   属于反向查询  if 设置related_name,那么related_name的值,没有设置,按表明_set
             publish_obj=models.Publish.obejcts.filter(name="人民出版社").first()
             book_list=publish_obj.bookList.all()
             for book in book_list:
                  print(book.title)
                  
         (3) alex 出版社过得所有书籍的名称    属于反向查询 if 设置related_name,那么related_name的值,没有设置,按表明_set
             alex=models.Author.obejcts.get(name="alex")
             book_list=alex.book_set.all()
             for book in book_list:
                  print(book.title)    
                  
         (4) 作者alex的所在地址  正向查询 按字段  反向查询 按表名
             alex=models.Author.obejcts.get(name="alex")
             alex.authordetail.addr
             
              
    ----  基于QuerySet   双下划线:   正向查询:按字段     反向查询:按表名    key:  1 过滤条件  2 查询结果

         (1) 查询Linux这本书的出版社名称和作者名字   属于正向查询  按关联字段
              
             models.Book.obejcts.filter(title="linux").values("publisher__name") # [{"publisher__name":"人民出版社"}]
             models.Book.obejcts.filter(title="linux").values("authors__name")   #
             
             
         (2) 人民出版社出版过的所有书籍名称 
             
             models.Book.obejcts.filter(publisher__name="人民出版社").values("title")

             models.Publish.obejcts.filter(name="人民出版社").values("book__title")         
             
         (3) alex 出版社过得所有书籍的名称
         
             models.Book.obejcts.filter(authors__name="alex").values("title")
         
             models.Author.obejcts.filter(name="alex").values("book__title")
             
             
View Code

 

posted @ 2017-11-26 21:35  wateligx  阅读(487)  评论(0编辑  收藏  举报