zoukankan      html  css  js  c++  java
  • 分组查询概念,聚合函数,字段

    一、今日内容

    '''
    注意:在2.x Django版本中,建立外键连接时,要明确on_delete=models.CASCADE这个字段属性,才拥有联级删除
    1. 分组查询概念
    2. 聚合函数
    3. 字段
    '''

    二、分组查询概念

    '''
    Book: id  name  price  publish_date  publish(publish_id)
    
    1. 聚合函数可以单独使用: 将整张表作为一个大的分组,查询字段只能是聚合结果
    select max(price), group_concat(name) from book where id < 10;
    
    2. 聚合函数在分组下使用,查询字段是聚合结果和分组字段
    select publish_id, max(price) from book group by publish_id having max(price) > 50
    
    '''

    三、聚合查询

    '''
    # 聚合函数的使用场景
        -- 单独使用:不分组,查询字段只能是聚合结果
        -- 分组使用:按字段分组,查询字段是分组字段和聚合结果
    
    # 导入聚合函数
    from django.db.models import Avg, Max, Min, Count, Sum
    '''

    四、单独聚合查询:aggregate

    '''
    # 语法:
    aggregate(别名=聚合函数('字段'))
    
    # 规则:
    1.可以同时对多个字段进行聚合处理:aggregate(别名1=聚合函数1('字段1'), ..., 别名n=聚合函数n('字段n'))
    3.是QuerySet对象方法(在QuerySet类型的数据后直接用.调用)
    2.方法返回值为dict类型
    
    # 案例:所有书中最贵和最便宜的书的价格
    dic = Book.objects.all().aggregate(high_price=Max('price'),low_price=Min('price))
    print(dic)
    如果在aggregate之前调用values操作,这个操作会被直接忽略
    '''

    五、组聚合查询:annotate

    '''
    # 语法:
    values('分组字段').annotate(别名=聚合函数('字段')).filter(聚合字段别名条件判断).values('要取的分组字段', '要取的聚合字段别名')
    
    # 规则:
    1.values(...).annotate(...)为分组组合,values控制分组字段,annotate控制聚合字段,得到QuerySet类型
    2.values可按多个字段分组values('分组字段1', ..., '分组字段n')
    3.可以同时对多个字段进行聚合处理annotate(别名1=聚合函数1('字段1'), ..., 别名n=聚合函数n('字段n'))
    4.分组后的的filter(...)代表having判断,只对聚合字段进行条件判断,可以省略(如果对非聚合字段或分组字段进行条件判断则代表where判断)
    5.取字段值values(...) 
    ①如果省略默认取所有分组字段与聚合字段
    ②没有省略,可以自主取个别分组字段及聚合字段(取字段的values中出现了非分组或非聚合字段,该字段自动成为分组字段)
    
    # 案例:每个出版社出版的最贵的书的价格高于50元的出版社名与最高价格
    res=Book.objects.all().values('publish__name').annotate(high_price=Max('price')).filter(high_price__gt=50).values('publish__name', 'high_price')
    print(res)
    
    res=Publish.objects.values('name').annotate(high_price=Max('book__price')).filter(high_price__gt=50).values('name','high_price')
    print(res)
    '''

    六、常用共有字段属性

    '''
    1. null:默认为False(字段不能为空,插入数据时该字段必须赋值),True表示字段可为null,空值将会被存储为NULL(插入数据时该字段可以为空)
    2. blank:默认为False(字段不允许为空),True表示字段可为空
    #null与blank区别:null纯粹是与数据库相关的,而blank则与验证相关,如果一个字段设为blank=True,表单验证时允许输入一个空值,而blank=False.则该项必须输入数据
    
    3. choices:可选的,限制了该选项的字段值必须是所指定的choice中的一个:
       choices为元组中套元组
       ①子元组的第一个值类型要与字段类型对应.
       ②第二个值可以代表第一个值的特殊含义
       ③通过get_tagName_display()获取特殊含义
       
        #models中字段设置        
        -- choices=((0, '女'), (1, "男"))  
        -- sex = models.SmallIntegerField(choices=choices)
        
        #取值
        -- obj.sex #取到的值是0或1 
        -- obj.get_sex_display()  #取到的值是女或男
    
    4. db_column:自定义字段名,没必要这样做
    5. db_index:如果为True的话,设置索引
    6. default:字段默认值
    7. editable:默认为True,若为False,则不会在/admin/界面显示
    8. primary_key:若设置为True,则表示将该字段设置为主键。一般情况下django默认会设置一个自增长的id主键。
    9. unique:若设置为True,该字段值不可重复,唯一键
    '''

    七、常用字段

    '''
    1. AutoField():默认自增主键(primary_key=True),django会默认建立id字段主键
    2. BooleanField():布尔字段,对应数据库tinyint类型
    3. CharField():字符类型
        -- 字段属性max_length=64,数据长度,必须明确
    4. DateField():年月日时间类型
        -- 字段属性auto_now=True,数据被更新时就会更新时间
        -- 字段属性auto_now_add=True,数据第一次产生时产生
    5. DateTimeField():年月日小时分钟秒时间类型
        -- 字段属性auto_now=True,数据被更新时就会更新时间
        -- 字段属性auto_now_add=True,数据第一次产生时产生
    6. DecimalField():混合精度的小数类型
        -- 字段属性max_digits=3,限定数字的最大位数(包含小数位)
        -- 字段属性decimal_places=2,限制小数的最大位数
    7. IntegerField():整型
    '''

    八、不常用字段

    '''
    1. BigAutoField():大整型自增
    2. BigIntegerField():长整型
    3. EmailField():邮箱字段,拥有/admin/验证
    4. FloatField():浮点型小数
    5. SmallIntegerField():小整型
    6. TextField():大文本类型
    7. FileField():文件字段
    '''

    九、关系字段

    '''
    1. ForeignKey():外键字段
        -- 字段属性to关联模型类
        -- 字段属性to_field关联字段,省略默认关联主键
        -- 字段属性on_delete (外键关联数据被删除时的操作)
            -- models.CASCADE 级联删除
            -- modles.PROTECT 抛出异常
            -- models.SET_NULL 设置空值
            -- models.SET_DEFAULT 设置默认值
            -- models.SET(value)自定义值
        -- 字段属性related_name自定义反向查询的字段名
        -- 字段属性db_constraint=False取消关联关系,但还可以使用连表查询
    总结:models.ForeignKey(to='关联的类名', null=True, on_delete=models.SET_NULL, db_constraint=False, related_name="本类名小写")
    # null=True, on_delete=models.SET_NULL 当一个表中的数据被删除时,与之关联的表的数据的外健字段值会被删除,并设置默认值为null
    #related_name 没有设置别名 Test1.objects.first().test2_set.first().name
                  设置别名     Test1.objects.first().别名.first().name
    
    2、OneToOneField():一对一外键字段
        -- 字段同外键
    3、ManyToManyField():多对多关系字段
        -- 字段属性to关联模型类
        -- 字段属性through关联关系类
        -- 字段属性through_fields关联关系表中(本身类名小写字段, 关联表类名小写字段)
    '''

    十、断开外键关联的ForeignKey使用

    '''
    # 1、不使用ForeignKey方式断开关联,不再支持Django ORM连表查询语法
    class Publish(models.Model):
        name = models.CharField(max_length=20)
    class Book(models.Model):
        name = models.CharField(max_length=20)
        # 字段需要写_id来表示相关表的字段信息
        publish_id = models.IntegerField()
    
    #查询的方法
    b1 = Book.objects.first()
    print(b1)
    p1 = Publish.objects.filter(pk=b1.publish_id).first()
    print(p1.name)
    
    
    # *****
    # 2、使用ForeignKey方式用db_constraint=False字段属性断开关联,依然支持Django ORM连表查询语法,建议使用
    class Publish(models.Model):
        name = models.CharField(max_length=20)
    class Book(models.Model):
        name = models.CharField(max_length=20)
        # 字段不需要写_id来表示相关表的字段信息,ORM会自动添加
        publish = models.ForeignKey(to='Publish', null=True, on_delete=models.SET_NULL, db_constraint=False)
        
    '''

    十一、断开关联的多对多自动创建关系表

    '''
    # *****
    # 使用ManyToManyField方式用db_constraint=False字段属性断开关联,依然支持Django ORM连表查询语法,建议使用,使用后依旧拥有add|clear|remove|set操作
    class MyBook(models.Model):
        name = models.CharField(max_length=20)
        my_author = models.ManyToManyField(to='MyAuthor', db_constraint=False)
    class MyAuthor(models.Model):
        name = models.CharField(max_length=20)
    '''

    十二、断开关联的多对多手动创建关系表

    # 手动创建关系表可以让关系表拥有更多的自身的字段,同时通过关系表类名可以直接获取第三张表
    '''
    # ****
    # 1、和自动建立关系表类似,依然支持Django ORM连表查询语法(多对多借助关系表连表查询)
    class Book(models.Model):
        name = models.CharField(max_length=20)
        
    class Author(models.Model):
        name = models.CharField(max_length=20)
        
    class Book_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()
    
    #借助关系表连表查询
    Book.objects.filter(pk=1).values('book_author__author__name')
    '''
    
    '''
    # ***
    2、手动创建关系表,在关系表中用ForeignKey方式支持基于外键关系表的ORM连表查询,同时明确ManyToManyField字段,所以也支持ORM正向方向连表查询
        -- db_constraint=False断开关联可以在ForeignKey或ManyToManyField任意一方完成
    
    class Book(models.Model):
        name = models.CharField(max_length=20)
        # 明确through与through_fields,ManyToManyField才不会自动建立关系表
        author = models.ManyToManyField(to='Author', through='Book_Author', through_fields=('book_id', 'author_id'))
        
    class Author(models.Model):
        name = models.CharField(max_length=20)
        
    class Book_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()
     
    #查询
    ①可以用外健关系表的ORM连表查询
    Book.objects.filter(pk=1).values('book_author__author__name')
    
    ②也可以用ORM正向反向连表查询
    Book.objects.filter(pk=1).values('author__name')
    '''
    # 总结:手动创建第三张表,第三张表的增删改就采用关系表类名衍生的create|delete|update,就不再拥有add|clear|remove|set(因为关系表拥有自己的字段,这些方法无法直接操作这些字段)
  • 相关阅读:
    QButton
    注入
    SpringBoot热重启配置
    centos7 安装 tomcat
    centos 安装jdk
    spring boot (6) AOP的使用
    spring boot (5) 自定义配置
    spring boot (4) 使用log4 打印日志
    SpringBoot (3)设置支持跨域请求
    spring boot (2) 配置swagger2核心配置 docket
  • 原文地址:https://www.cnblogs.com/lizeqian1994/p/10493279.html
Copyright © 2011-2022 走看看