• Django框架08 /聚合查询、分组、F/Q查询、原生sql相关


    Django框架08 /聚合查询、分组、F/Q查询、原生sql相关

    1. 聚合查询

    • aggregate(*args, **kwargs)

    • aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

    • 代码示例:

      # 计算所有图书的平均价格
      >>> from django.db.models import Avg
      >>> Book.objects.all().aggregate(Avg('price'))
      # 结果:
      	{'price__avg': 34.35}
          
      >>> Book.objects.all().aggregate(a=Avg('price'))   # 或者给它起名字:aggretate(a=Avg('price'))
      # 结果:
      	{'a': 34.35}    
      >>> Book.objects.aggregate(average_price=Avg('price'))
      # 结果:
      	{'average_price': 34.35}  
      
    • 如果希望生成不止一个聚合,可以向aggregate()子句中添加另一个参数。

      例如:如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

      >>> from django.db.models import Avg, Max, Min
      >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
      # count('id'),count(1)也可以统计个数
      
      #结果:
      	{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
      

    2. 分组

    • annotate

    • 代码示例:

      models.Publish.objects.annotate(avg_price=Avg('book__price')).values('avg_price')
      # objects后面不写values默认是以id为依据分组
      
      models.Book.objects.values('publish_id').annotate(avg_price=Avg('price')) 
      # objects后面写values,以values里边的字段为依据进行分组
      # 结果:
      # {'pulish_id':1,'avg_price':11.11}
      
      # 分组后排序:
      Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
      
    • 注意:annotate里面必须写个聚合函数,不然没有意义,并且必须有个别名=,别名随便写,但是必须有,用哪个字段分组,values里面就写哪个字段,annotate其实就是对分组结果的统计,统计你需要什么。

    3. F查询和Q查询

    • F查询 /针对自己单表中字段的比较和处理

      from django.db.models import F
      
      models.Book.objects.filter(good__gt=F('comment'))
      models.Book.objects.all().update(price=F('price')+100)
      
    • Q查询 /与& 或| 非~/针对多个条件的或与非进行查询

      from django.db.models import Q
      
      filter(Q(xx=11)|Q(ss=22)&Q(oo=33))
      filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33))   # &优先级高,先执行后面的&运算,再执行前面的|运算
      filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33),name='dd')   # 逗号(,)隔开的话,优先级是先执行完前面的或(|),再执行逗号(,)后面的and关系
      

    4. orm执行原生sql

    • 方式一:只能对本表进行原生sql操作

      models.Publish.objects.raw('原生sql')
      # <RawQuerySet: select * from app01_publish;>
      
      # 代码示例:
      def test(request):
      ret = models.Publish.objects.raw('select * from app01_publish;')
      for i in ret:
          print(i)
      return HttpResponse('Test is completed')
      
    • 方式二:对所有的表都可以进行原生sql操作

      from django.db import connection
      cursor = connection.cursor()
      cursor.execute(sql,[arg,])  # [arg,] -- 参数
      cursor.fetchall()
          
      # 代码示例:    
      from django.db import connection
      cursor = connection.cursor()
      cursor.execute('select * from app01_publish;')
      print(cursor.fetchall())
      return HttpResponse('Test is completed')
      

    5. 展示orm转换成原生sql语句

    • 显示orm语句转换成的原生sql语句

      models.Book.objects.filter(good__gt=F('comment')*2)
      from django.db import connection
      print(connection.queries)
      

    6. 设置 sql_mode

    • 1.查看当前会话的sql_mode:

      select @@sql_mode
      
    • 2.设置当前会话的sql_mode:

      set @@sql_mode = 'only_full_group_by';
      
    • 3.设置全局会话的sql_mode:

      set global sql_mode = 'only_full_group_by';
      
    • 4.在配置文件中修改

    7. orm查询示例

    • 代码示例:

      def test(request):
          from django.db.models import Max,Avg,Q
          # 1 查询每个作者的姓名以及出版的书的最高价格
          ret = models.Author.objects.annotate(max_price=Max('book__price')).values('name','max_price')
          print(ret)
          
          # 2 查询作者id大于2作者的姓名以及出版的书的最高价格
          ret = models.Author.objects.filter(id__gt=2).annotate(max_price=Max('book__price')).values('name','max_price')
          print(ret)
      
          # 3 查询作者id大于2或者作者年龄大于等于20岁的女作者的姓名以及出版的书的最高价格
          ret = models.Author.objects.filter(Q(id__gt=2)|Q(age__gte=20),sex='female').annotate(max_price=Max('book__price')).values('name','max_price')
          print(ret)
      
          # 4 查询每个作者出版的书的最高价格的平均值
          ret = models.Author.objects.annotate(max_price=Max('book__price')).aggregate(Avg('max_price'))
          print(ret)
      
          # 5 每个作者出版的所有书的最高价格以及最高价格的那本书的名称(orm查询会有问题)
          ret = models.Author.objects.annotate(a=Max('book__price')).values('a','book__title')
          print(ret)
          # 分组后取到的书名只有一个,取的都是每组的第一个
      
          # 原生sql查询
          # select * from
          # (select app01_author.id, app01_book.title, app01_book.price from app01_author 
          # inner join app01_book_authors on app01_author.id=app01_book_authors.author_id
          # inner join app01_book on app01_book_authors.book_id=app01_book.id order by app01_book.price)
          # as t1 group by t1.id;
          return HttpResponse('Test is completed')
      
      # 注意点:
      # 1.as t1 是将查出来的一张虚拟表合并成一张表,里边有重复的字段合不成一张表(同一张表不能出现重复的字段),应该select出需要的字段,再合并成一张表
      # 2.分组是对新合成的t1表进行分组
      
  • 相关阅读:
    SQL操作全集 sql精典收藏
    sql中全角字符与半角字符检验问题
    asp.net目录权限设置图文综合[转]
    XPath 语法
    XPath学习
    接口使用例子,阐述接口的优点、作用
    sql查询出表中所有列名 判断两个表中的列是否相同
    指定键让指定的按钮提交
    C#.Net网络程序开发Socket篇
    ASP.NET中异常处理使用
  • 原文地址:https://www.cnblogs.com/liubing8/p/11644787.html
Copyright © 2020-2023  润新知