聚合查询、聚合函数

聚合查询、聚合函数

用法:
from django.db.models import Avg,Sum,Max,Count,Min
聚合:
示例:
models.Book.object.all().aggregate(Avg("price"))
你也可以在聚合子句中用它
models.Book.object.aggregate(average_price=Avg('price'))
你也可以连续的使用
models.Bool.object.all().aggregate(Avg("price"),Max("price"),Min("price"))

分组查询
统计每一本书的作者的个数
models.Book.object.all().annotate(author_num=Count("author"))
统计出每个出版社卖的最便宜的书的价格
sss

统计不止一个作者的书
models.Book.object.annotate(author_num=Count("author")).filter(author_num__get=1)

查询各个作者出的书的总价格
models.Author.object.annotate(sum_price=Sum("book__price")).values("name","sum_price")

总结

value里面的参数对应的是sql语句中的select要查找的显示字段,

filter里面的参数相当于where或者having里面的筛选条件,

annotate本身表示group by的作用,前面找寻分组的依据,内部放置显示可能用到的聚合运算式,后面跟filter来增加限制条件,最后的value来表示分组想要查找的字段

F与Q查询

F查询:
Django提供F()来做比较查询,F()的实例可以在查询中引用字段,来比教同一个model实例中两个不同的字段的值.

示例:
1.查询出卖出数大于库存数的书籍
from django.db.models import F  #先导入F模块
res = models.Book.objects.filter(maichu__gt=F('kuncun'))
F可以帮我们取到某个字段对应的值来当做我的筛选条件,而不是我指定的了,他实现了一个动态比较的效果.

Django支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作.基于此我们就可以对表中的数值类型进行数学运算

2.将每个书籍的价格提高50元
models.Book.objects.update(price=F('pirce')+50) #很简单吧.

3.拼接char字段.
如: 我们要把书名后面加上'新款'(这个时候需要对字符串进行拼接Concat操作,并且要加上拼接值(Value)
from django.db.models.functions import Concat
from django.db.models import Values
res = models.Book.object.update(name=Concat(F('name').Value('新款')))
Concat表示的是进行字符串的拼接操作,参数位置决定了拼接在头部还是在尾部,Value里面是要新增的拼接值
Q查询
filter()等方法中用逗号隔开的条件是与的关系.如果你想要执行更复杂的语句(例如or语句).你可以使用Q对象.

示例:
1.查询出卖出数大于100或者价格小于100块的
from django.db.models import Q   #导入Q模块
models.Book.objects.filter(Q(maichu__gt=100)|Q(price__lt=100)) #对条件包裹Q,实现或者

2.示例:
查询库存数是100并且卖出数不是0的数
models.Book.object.filter(Q(kucun=100)&`Q(maichu=0))
&表示并且,`表示取反

事务

事务的定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败则回滚到原来的状态,保证数据的完整性和一致性

#django开启事务
事务四大特性: 原子性, 一致性, 隔离性, 持久性
from django.db import transaction
with transaction.atomic():

几个重要的方法比较

update()和save()的区别

两者都是对数据的修改保存操作,但是save()函数是将数据列的全部数据项全部都重新写一遍,而update()则是针对修改的项进行针对的更新它频率高耗时少

select_related和prefetch_related

def select_related(self, *fields)
    性能相关:表之间进行join联表操作,一次性获取关联的数据
    
    总结:
      1.select_related主要针对一对一和多对一的关系进行优化
      2.select_related使用sql的join语句进行优化,减少sql的查询次数,来提高性能

def prefetch_related(self, *lookups)
    性能相关: 多表联表操作时速度会很慢,它是使用多次sql查询在python中实现联表操作
    
    总结:
      1.对于多对多字段和一对多字段,可以使用prefetch_related()来进行优化
      2.prefetch_related()的优化方式是分别查询每个表,然后用python来处理他们之间的关系

方法大全

def all(self)
    #获取所有的数据对象
    
def filter(self, *args, **kwargs)
    #条件查询
    #条件可以是: 参数, 字典, Q
def exclude(self, *args, **kwargs)
    # 条件查询
    # 条件可以是:参数,字典,Q

def select_related(self, *fields)
    性能相关:表之间进行join连表操作,一次性获取关联的数据。

    总结:
    1. select_related主要针一对一和多对一关系进行优化。
    2. select_related使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。

def prefetch_related(self, *lookups)
    性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。

    总结:
    1. 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。
    2. prefetch_related()的优化方式是分别查询每个表,然后用Python处理他们之间的关系。

def annotate(self, *args, **kwargs)
    # 用于实现聚合group by查询

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

    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
    # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id

    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)
    # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1

    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)
    # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1

def distinct(self, *field_names)
    # 用于distinct去重
    models.UserInfo.objects.values('nid').distinct()
    # select distinct nid from userinfo

    注:只有在PostgreSQL中才能使用distinct进行去重

def order_by(self, *field_names)
    # 用于排序
    models.UserInfo.objects.all().order_by('-id','age')

def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    # 构造额外的查询条件或者映射,如:子查询

    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

 def reverse(self):
    # 倒序
    models.UserInfo.objects.all().order_by('-nid').reverse()
    # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序


 def defer(self, *fields):
    models.UserInfo.objects.defer('username','id')
    或
    models.UserInfo.objects.filter(...).defer('username','id')
    #映射中排除某列数据

 def only(self, *fields):
    #仅取某个表中的数据
     models.UserInfo.objects.only('username','id')
     或
     models.UserInfo.objects.filter(...).only('username','id')

 def using(self, alias):
     指定使用的数据库,参数为别名(setting中的设置)

猜你喜欢

转载自www.cnblogs.com/kangwy/p/11743198.html