聚合查询、聚合函数
聚合查询、聚合函数
用法:
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中的设置)