zoukankan      html  css  js  c++  java
  • ORM-分组查询、F/Q查询

    一、 F查询和Q查询

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

    Q 可以和&、|、~搭配使用

    # 评论数大于点赞数
     obj = models.Book.objects.filter(comment__gt=F('good'))
     print(obj)
    
    # 评论数是大于点赞数的1.5倍
     obj = models.Book.objects.filter(comment__gt=F('good')*1.5)
     print(obj)
    
    # 修改价格
     models.Book.objects.all().update(
         b_price=F('b_price')+1
    )
    
    # 查询年龄大于50岁的男性作者
    obj = models.Author.objects.filter(a_sex='male', a_age__gt=50)
    print(obj)
    obj = models.Author.objects.filter(Q(a_sex='female')&Q(a_age__lte=45))
    print(obj)
    

    二、分组查询

    1、obj = xxx. annotate(yyy). values('zzz')————————>以xxx的主键为分组依据

    2、obj = xxx. values('aaa')annotate(yyy). values('zzz')————————>以aaa为分组依据

    #查询每个出版社出版书籍的平均价格
    obj = models.Book.objects.values('publish_id').annotate(a=Avg('b_price')).values('a')
    print(obj)
    
    #查询每个出版社的名字及其对应出版书籍的最高价格
    obj = models.Publisher.objects.values('p_name').annotate(a=Max('book__b_price')).values('p_name', 'a')
    print(obj)
    
    
    # 查询每一个出版社的id以及其出版的书对应的平均价格
    obj = models.Publisher.objects.annotate(a=Avg('book__b_price')).values('p_id', 'a')
    print(obj)
    
    # 查询每本书的id以及对对应的作者的最大年龄
    obj = models.Book.objects.annotate(a=Max('authors__a_age')).values('b_id', 'a')
    print(obj)
    
    # 查询每个作者的姓名及出版的书的最高价格
    obj = models.Author.objects.annotate(a=Max('book__b_price')).values('a_name', 'a')
    print(obj)
    
    # 查询作者id大于3作者的姓名以及出版社的平均价格
    obj = models.Author.objects.filter(a_id__gt=3).annotate(a=Avg('book__b_price')).values('a_name', 'a')
    print(obj)
    # 查询作者id大于2或者作者年龄大于20岁的女作者的姓名及出版的书的最高价格
    obj = models.Author.objects.filter(Q(a_id__gt=20) | Q(a_age__gt=40), a_sex='male').annotate(a=Max('book__b_price')).values('a_name', 'a')
    print(obj)
    
    # 查询每个作者出版的书的最高价格的平均值
    obj = models.Author.objects.annotate(a=Max('book__b_price')).values('a').aggregate(b=Avg('a'))
    print(obj)
    
    # 每个作者出版的所有书的价格以及最高价格的那本书的名称
    '''不能用ORM分组,因为ORM分组存在局限性,哪里出错具体看一下代码'''
    '''
    SELECT MAX(`app01_book`.`b_price`) AS `a` FROM `app01_author` LEFT OUTER JOIN `app01_book_authors` 
    ON (`app01_author`.`a_id` = `app01_book_authors`.`author_id`) LEFT OUTER JOIN `app01_book` 
    ON (`app01_book_authors`.`book_id` = `app01_book`.`b_id`) 
    GROUP BY `app01_author`.`a_name` ORDER BY NULL LIMIT 21; args=()
    '''
    # 正确
    obj = models.Author.objects.values('a_name').annotate(a=Max('book__b_price')).values('a')
    print(obj)
    
    '''
    SELECT `app01_book`.`b_title`, MAX(`app01_book`.`b_price`) AS `a` 
    FROM `app01_author` LEFT OUTER JOIN `app01_book_authors` 
    ON (`app01_author`.`a_id` = `app01_book_authors`.`author_id`) 
    LEFT OUTER JOIN `app01_book` ON (`app01_book_authors`.`book_id` = `app01_book`.`b_id`) 
    GROUP BY `app01_author`.`a_name`, `app01_book`.`b_title` ORDER BY NULL LIMIT 21; args=()
    
    '''
    # 出错,因为以作者名分组,只能取作者名(分组依据)和a(筛选出的值),其余的值不能正确的筛选出,默认取那个组的第一条记录
    obj = models.Author.objects.values('a_name').annotate(a=Max('book__b_price')).values('book__b_title', 'a')
    print(obj)
    
    '''解决办法,用元素sql语句写'''
    SELECT app01_author.a_name, MAX(app01_book.b_price) FROM (app01_author INNER JOIN app01_book_authors ON app01_author.a_id=app01_book_authors.author_id
    INNER JOIN app01_book ON app01_book_authors.book_id=app01_book.b_id) GROUP BY app01_author.a_name;  #没问题
    
    
    SELECT app01_author.a_name, MAX(app01_book.b_price), app01_book.b_title FROM (app01_author INNER JOIN app01_book_authors ON app01_author.a_id=app01_book_authors.author_id
    INNER JOIN app01_book ON app01_book_authors.book_id=app01_book.b_id) GROUP BY app01_author.a_name;  #报错
    
    #该题目正确sql语句(方法一)
    '''注意要设置'''
    SELECT tt.aa, app01_book.b_price FROM(SELECT app01_author.a_id as aa, MAX(app01_book.b_price) as bb FROM app01_author INNER JOIN app01_book_authors ON app01_author.a_id=app01_book_authors.author_id
    INNER JOIN app01_book ON app01_book.b_id=app01_book_authors.book_id GROUP BY app01_author.a_id) as tt
    INNER JOIN app01_book_authors ON app01_book_authors.author_id=tt.aa
    INNER JOIN app01_book ON app01_book_authors.book_id=app01_book.b_id
    WHERE tt.bb=app01_book.b_price
    
    #该题目正确sql语句(方法二,利用排序,分组后只能取上面的那一行,那把我们通过排序将想要的那一行放在上面)
    '''注意sql_mode此时不能设置成 ONLY_FULL_GROUP_BY'''
    SELECT * FROM (SELECT app01_author.a_id, app01_book.b_price, app01_book.b_title FROM app01_author INNER JOIN app01_book_authors ON app01_author.a_id=app01_book_authors.author_id
    INNER JOIN app01_book ON app01_book.b_id=app01_book_authors.book_id ORDER BY app01_book.b_price desc) as tt
    GROUP BY a_id
    

    三、 sql_mode设置

    1. 查询sql_mode的语句:select @@sql_mode
    2. 查询全局sql_mode的语句:select @@global.sql_mode
    3. 设置零时sql_mode的语句:set sql_mode='ONLY_FULL_GROUP_BY'(这是零时会话,只针对于当前会话客户端有效,一关闭或其它客户端没用)
    4. 设置全局sql_mode的语句: set global sql_mode='ONLY_FULL_GROUP_BY'(这是永久会话,对所有客户端都有用,但一旦mysql服务端已重启,就失效)
    5. 最终解决办法:先设置global sql_mode,然后在配置文件中修改sql_mode。

    四、 在orm中执行原生sql语句

    Django 提供两种方法使用原始SQL进行查询:

    1. 使用raw()方法,进行原始SQL查询并返回模型实例;(raw()语法查询必须包含主键)

    2. 完全避开模型层,直接执行自定义的SQL语句。

      from django.db import connection, connections
      cursor = connection.cursor()  # cursor = connections['default'].cursor()
      cursor.execute("""SELECT * from auth_user where id = %s""", [1])
      ret = cursor.fetchone()
      
  • 相关阅读:
    视图、触发器、事务、存储过程、函数,流程控制
    权限管理,pymysql模块
    单表查询
    sql逻辑查询语句的执行顺序
    Mysql数据库基础知识
    库,表,记录的相关操作
    并发编程之IO模型
    并发编程之协程
    并发编程之多线程
    事件委托
  • 原文地址:https://www.cnblogs.com/messi-mu/p/14284537.html
Copyright © 2011-2022 走看看