Django分组聚合查询实例分享
多表查询
1.增删改
一对多:先一后多,外键可以为对象或依赖表的主键(publishandbook)
publish=Publish.objects.create() Book.objects.create(....publish=publish|publish_id=publish.id)
删:默认存在级联删除
改:book修改外键,外键一定存在
多对多:
关系表的获取(book(主键)andauthor)book.author
增:book.author.add(作者对象们|主键们)
删:clear()清除remove()可删除单个作者
改:set([作者对象们|主键们])
2.查
基于对象,正向找属性,反向找类名小写,多条记录类名小写_set
book.publish.first().name(book一定是对象,不是queryset) publish.book_set.first().name
基于双下划线:
Book.objects.filter(id=1).values('publish__name')[0](values查出的也是queryset) publish.values('book__name')
今日内容
1.分组查询:聚合结果group_by()
2.聚合函数
3.字段
分组查询(单独聚合查询and分组聚合查询---基于mysql)
Book:idnamepricepublish_datepublish
聚合函数可以单独使用----整张表是一个大组
selectmax(price)frombook
聚合函数在分组下使用
selectmax(price)ashigh_pricefrombookgroupbypublishhavinghigh_price>50;
聚合查询---基于ORM
聚合函数的使用场景:
单独使用:不分组,只查聚合结果
分组使用:按字段分组,可查分组字段与聚合结果
导入聚合函数:
fromdjango.db.modelsimportAvg,Max,Min,Count,Sum
单独聚合查询:aggregate(聚集,合集)---不分组
#语法
#聚合函数:Max,Min,Sum,Avg,Count
aggregate(别名=聚合函数('字段‘)
规则:
1.可以同时对多个字段进行聚合处理:aggregate(name1=,name2=...)
2.是QuerySet对象的方法(all,filter)
3.返回值为dict类型
4.在aggregate之前的values操作没作用,被忽略
例:所有书中最贵的书的价格
dic=Book.objects.all().aggregate(high_price=max('price),low_price=min('price'))
分组聚合查询:annotate(注释,做注解)---分组
#语法
values('分组字段').annotate(别名=聚合函数(‘字段').filter(聚合别名条件).values('取分组字段','取聚合字段别名'))
规则:
1.values---annotate分组组合,values控制分组的字段,annotate控制聚合字段
2.values可以按多个字段分组values('字段1‘,'字段2‘)
3.可以同时对多个字段进行聚合处理annotate(别名1=max('price'),别名2=min('price'))
4.分组后的filter代表having判断,只对聚合字段进行条件判断,(参数为非聚合或分组进行条件判断代表where判断)
5.取字段值values()省略默认取所有分组字段和聚合字段,也可以自己定义(对非分组或非聚合字段,该字段自动被变成分组字段)
#案例:每个出版社出版的最贵的书的价格高于50元的出版社名与最高价格
#思路:按出版社分组(从book出发),high_price=max('price'),filter(high_price__gt=50)
#每个组的价格最贵的
Book.objects.all().values('publish__name').annotate(high_price=max('price').filter(high_price__gl=50).values('publish__name','high_price'))
字段属性
1.null:默认Fasle(默认字段不能为空),True表示字段可为null
2.blank:默认False,True表示字段可以为空
3.choice:限制了该选项字段值必须是指定的choice中的一个(元组套元组)
sex=models.SmallIntegerField(choice=((1,'man'),(2,'female')))
obj.get_sex_display()有choices这个字段的:要取得'女‘或'男‘,get_字段名sex_display()--超出失效
4.db_column:自定义字段名
db_column='gender'起别名该sex
5.db_index:True设置索引
6.default:字段默认值
7.editable:默认为True,False:不在admin界面显示
8.primary_key:TRUE为主键,
9.unique:true字段值不可重复
字段
1.AutoField():默认自增主键(primary_key=True)
2.BooleanField():布尔字段,对应databasetinyint类型
3.CharField():字符类型(默认不为空)
max_length=20,null=True可以为空
4.DateField():年月日
auto_now=True数据别更新就会更新时间
auto_now_add=True数据第一次产生时
5.DateTimeField():年月日时分秒
auto_now=True数据别更新就会更新时间
auto_now_add=True数据第一次产生时
6.DecimalField():混合精度的小数类型
max_digits=5,含小数为的最大位数
decimal_places=2,小数位数
7.IntegerField():整型
不常用字段
关系字段
1.ForeignKey():外键字段
to=关联模型类(一对多)
to_file=关联字段,省略默认关联主键
on_delete(外键关联数据被删除时的操作)
models.CASCADE级联删除
modles.PROTECT抛出异常
models.SET_NULL设置空值
modles.SET_DEFAULT设置默认值
models.SET(value)自定义值
related_name自定义反向查询的字段名
db_constraint=False,取消关联,但还可以使用链表查询
总结:models.ForeignKey(to='relatedclassname',null=True,on_delete=models.SET_NULL,db_constraint=False,related_name='本类名小写')
2.OneToOneField():一对一字段
同外键
3,ManyToManyField():多对多关系
to=关联模型类
through=关联关系类
through_fields关联关系表中(本身字段,关联字段)
断开外键关联的ForeignKey使用(一对多,一对一)
#一对多查询----(publishandbook)
#方式一:不使用外键,在book中添加publish_id属性
#不在支持DjangoORM链表查询语法#classBook(models.Model):
#name=models.CharField(max_length=20)
#publish_id=models.IntegerField(null=True)
#
#classPublish(models.Model):
#name=models.CharField(max_length=20)
#
##查询方式:
##通过第一本书book找出版社
##id=Book.objects.first().publish_id
##publish=Publish.objects.filter(id=id)[0].name
##print(publish)方式二:使用外键,用db_constrain=False字段段开连接
#可以使用DjangoORM连表查询语法
classBook(models.Model):
name=models.CharField(max_length=20)
publish=models.ForeignKey(to='Publish',db_constraint=False,null=True,on_delete=models.SET_NULL)#to_field='id'不写会自动添加classPublish(models.Model):
name=models.CharField(max_length=20)#书的出版社(外键方式)
#print(Book.objects.first().publish.name)
#print(Book.objects.filter(pk=1).values('publish__name'))
断开关联---多对多自动创建关系表
#断开关联(db_constraint属性)的多对多自动创建关系表(book(外键)andauthor)
#断开后依然支持DjangoORMlianiao查询语法
#当新表中无需新加额外字段时,可以自动创建
classMyBook(models.Model):
name=models.CharField(max_length=20)
#这里会产生第三张表
book_author=models.ManyToManyField(to='MyAuthor',db_constraint=False)classMyAuthor(models.Model):
name=models.CharField(max_length=20)
##查询方法
##多对多(自动创建第三张表):书的作者
#b1=MyBook.objects.first()
##b1.book_author这个是关系表
#forauthorinb1.book_author.all():
#print(author.name)#print(MyBook.objects.filter(pk=1).values('book_author__name'))
断开关联---多对多手动创建关系表
#手动创建关系表的原因:可以拥有自身字段,可以通过关系表类名直接获取第三张表
#手动创建关系表可以让关系表可以拥有更多的自身的字段,同时通过关系表类名可以直接获取第三张表
'''
#****
#1、和自动建立关系表类似,依然支持DjangoORM连表查询语法(多对多借助关系表连表查询)
classBook(models.Model):
name=models.CharField(max_length=20)
classAuthor(models.Model):
name=models.CharField(max_length=20)
classBook_Author(models.Model):
book=models.ForeignKey(to="Book",null=True,on_delete=models.SET_NULL,db_constraint=False)
author=models.ForeignKey(to='Author',null=True,on_delete=models.SET_NULL,db_constraint=False)
time=models.DateField()
''''''
#****
2、手动创建关系表,在关系表中用ForeignKey方式支持基于外键关系表的ORM连表查询,同时明确ManyToManyField字段,所以也支持ORM正向方向连表查询
--db_constraint=False断开关联可以在ForeignKey或ManyToManyField任意一方完成
classBook(models.Model):
name=models.CharField(max_length=20)
#明确through与through_fields,ManyToManyField才不会自动建立关系表,没有关联关系后就不能再使用db_constraint字段属性
author=models.ManyToManyField(to='Author',through='Book_Author',through_fields=('book_id','author_id'))
classAuthor(models.Model):
name=models.CharField(max_length=20)
classBook_Author(models.Model):
book=models.ForeignKey(to="Book",null=True,on_delete=models.SET_NULL,db_constraint=False)
author=models.ForeignKey(to='Author',null=True,on_delete=models.SET_NULL,db_constraint=False)
time=models.DateField()
'''
#总结:手动创建第三张表,第三张表的增删改就采用关系表类名衍生的create|delete|update,就不再拥有add|clear|remove|set(因为关系表拥有自己的字段,这些方法无法直接操作这些字段)
到此这篇关于Django分组聚合查询实例分享的文章就介绍到这了,更多相关Django分组聚合查询内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!