ORM单表查询,跨表查询,分组查询

 

单表查询之下划线

models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and
类似的还有:startswith,istartswith, endswith, iendswith 
date字段还可以:
models.Class.objects.filter(first_day__year=2017)
 
#获取id大于1且小于10的值
print(models.Book.objects.filter(id__lt=,id__gt=))
# 查询 id 在 [, , , ]中的结果
print(models.Book.objects.filter(id__in=[,,,]))
# contains 字段包含指定值的
print(models.Book.objects.filter(title__contains="小单"))
# icontains 忽略大小写包含指定值
print(models.Book.objects.filter(title__icontains="NI"))
# 判断id值在 哪个区间的 SQL语句中的between and <= <=
print(models.Book.objects.filter(id__range=[,]))
# 日期和时间字段还可以有以下写法
ret = models.Person.objects.filter(birthday__year=)
ret = models.Person.objects.filter(birthday__year=, birthday__month=)
 

跨表查询操作

class Author(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=)
age=models.IntegerField()
# 与AuthorDetail建立一对一的关系
authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE) class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday=models.DateField()
telephone=models.BigIntegerField()
addr=models.CharField( max_length=) class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=)
city=models.CharField( max_length=)
email=models.EmailField()
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField( max_length=)
publishDate=models.DateField()
price=models.DecimalField(max_digits=,decimal_places=)
# 与Publish建立一对多的关系,外键字段建立在多的一方
publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
# 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
authors=models.ManyToManyField(to='Author',)

基于对象查询(子查询)


                   按字段(publish)
一对多 book -----------------> publish
<----------------
book_set.all()
 
 正向查询按字段:
查询python这本书籍的出版社的邮箱
python=models.Book.objects.filter(title="python").first()
print(python.publish.email)
反向查询按 表名小写_set.all()
苹果出版社出版的书籍名称
publish_obj=models.Publish.objects.filter(name="苹果出版社").first()
for obj in publish_obj.book_set.all():
print(obj.title)
 
                   按字段(authors.all())
多对多 book -----------------------> author
<----------------------
              book_set.all()
 
    查询python作者的年龄
python = models.Book.objects.filter(title="python").first()
for author in python.authors.all():
print(author.name ,author.age) 查询alex出版过的书籍名称 alex=models.Author.objects.filter(name="alex").first()
for book in alex.book_set.all():
print(book.title)
 

                     按字段 authorDetail
一对一 author -----------------------> authordetail
<----------------
按表名 author
    查询alex的手机号
alex=models.Author.objects.filter(name='alex').first()
print(alex.authorDetail.telephone)
查询家在山东的作者名字
ad_list=models.AuthorDetail.objects.filter(addr="shandong")
for ad in ad_list:
print(ad.author.name)
对应的sql:
select publish_id from Book where title="python"
select email from Publish where nid =

基于queryset和__查询(join查询)

正向查询:按字段  反向查询:表名小写

查询python这本书籍的出版社的邮箱
ret=models.Book.objects.filter(title="python").values("publish__email")
print(ret.query) select publish.email from Book
left join Publish on book.publish_id=publish.nid
where book.title="python" 苹果出版社出版的书籍名称
方式1:
ret1 = models.Publish.objects.filter(name="苹果出版社").values("book__title")
print("111111111====>", ret1.query)
# 方式2:
ret2 = models.Book.objects.filter(publish__name="苹果出版社").values("title")
print("2222222222====>", ret2.query) 查询alex的手机号
方式1:
ret = models.Author.objects.filter(name="alex").values("authorDetail__telephone") 方式2:
models.AuthorDetail.objects.filter(author__name="alex").values("telephone") 查询手机号以151开头的作者出版过的书籍名称以及书籍对应的出版社名称 ret = models.Book.objects.filter(authors__authorDetail__telephone__startswith="151").values('title', "publish__name")
print(ret.query)
# .正向查询 基于对象 跨表查询
book_obj = models.Book.objects.all().first() #对象
ret = book_obj.publisher # 和我这本书关联的出版社对象
print(ret, type(ret))
ret = book_obj.publisher.name # 和我这本书关联的出版社对象
print(ret, type(ret))
# .利用双下划线 跨表查询 双下划线就表示跨了一张表,基于Queryset
ret = models.Book.objects.filter(id=).values_list("publisher__name")
print(ret) #等同于 print( models.Book.objects.all().first().publisher.name)
print("反向查询".center(, "*"))
# 反向查询 . 基于对象查询
publisher_obj = models.Publisher.objects.get(id=) # 得到一个具体的对象
# ret = publisher_obj.book_set.all() #表名_set
ret = publisher_obj.books.all() #如果设置了related_name="books"
print(ret)
# . 基于双下划线 基于Queryset
ret = models.Publisher.objects.filter(id=).values_list("book__title")
print(ret)

聚合查询

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。
用到的内置函数:from django.db.models import Avg, Sum, Max, Min, Count
from django.db.models import Avg, Sum, Max, Min, Count
book_obj=models.Book.objects.all()
print(book_obj.aggregate(Max("price"))) #{'price__max': Decimal('9999.99')}
#指定一个名称
print(book_obj.aggregate(max_price=Max("price"))) #{'max_price': Decimal('9999.99')}
#生成多个聚合
print(book_obj.aggregate(Max("price"),Min("price"),Avg("price"))) #{'price__max': Decimal('9999.99'), 'price__min': Decimal('10.00'), 'price__avg': 1507.141429}

分组查询

1.和sql对比:
1.models.Employee Employee相当于sql中的from 后面的表名
2.annotate前面的values值相当于group by的字段
3.(a=Avg("salary"))里面如是跨表查询就需要使用双下划线,正查就字段__另一张表的字段,反查就另一张表明__字段
4.annotate后面的values 是select的字段
对应格式:select __ from ___ inner join ———— on ... group by ____
2.关键点:
1.queryset对象.annotate() annotate前面是queryset对象
2.annotate进行分组统计,按前面select的字段进行group by
3.annotate()返回值依然是queryset对象,增加了分组统计之后的键值对
 
.ORM中values或者values_list 里面写什么字段,就相当于select 什么字段
ORM分组查询 每个部门名称及部门的平均年龄
ret = models.Employee.objects.all().values("dept", "age")
SQL语句
"""
SELECT `employee`.`dept`, `employee`.`age` FROM `employee` LIMIT ; args=()
"""
.ORM中 annotate 前面是什么就按照什么分组
from django.db.models import Avg
ret = models.Employee.objects.values("province").annotate(a=Avg("salary")).values("province", "a")
相当于:
SELECT `employee`.`province`, AVG(`employee`.`salary`) AS `a` FROM `employee` GROUP BY `employee`.`province` ORDER BY NULL LIMIT ; args=()
print("分组查询".center(, "*"))
. ORM跨表分组查询,queryset对象跨表查询时使用双下划线
ret = models.Person.objects.values("dept_id").annotate(a=Avg("salary")).values("dept__name", "a")
反向:
"""
SELECT `dept`.`name`, AVG(`person`.`salary`) AS `a` FROM `person` INNER JOIN `dept` ON (`person`.`dept_id` = `dept`.`id`) GROUP BY `person`.`dept_id`, `dept`.`name` ORDER BY NULL LIMIT ; args=()
"""
.查询每一个部门的名称和人数
#正向查询:
models.emp.objects.values("dept_id").annotate(c=Count("name")).values("dept__name","c")
#反向查询
models.dep.objects.values("name").annotate(c=Count("emp__name")).values("name","c")
SQL: select dep_name Count(emp.name) from emp inner join dep on .... group by dep_id .查询每一个作者的名字及出版过的书籍的最高价
models.Author.objects.values('id').annotate(c=Max('book__price')).values("name","c")
##多对多的关系,在sql中跨了多张表
select __ from author inner join book_authors on .... inner join ... group by author.name
.查询每一本书作者的个数
models.Book.objects.values("id").annotate(c=Count("authors__name")).values("title","c")
ret=models.Book.objects.all().annotate(author_num=Count("author"))
for book in ret:
print("书名:{},作者数量:{}".format(book.title, book.author_num))
#查询每一个分类的名称及对应的文章数 models.Category.objects.values("id").annotate(c=Count("article__title")).values("title","c") 
.统计不止一个作者的图书(过滤完后显示) models.Book.objects.values("title").annotate(c=Count("authors__name")).filter(c__gt=).values('name',"c")
.查询各个作者出的书的总价格 ret = models.Author.objects.all().annotate(price_sum=Sum("books__price")) for i in ret: print(i, i.name, i.price_sum)
 
extra  --> 在执行ORM查询的时候执行额外的SQL语句
 
# 查询person表,判断每个人的工资是否大于2000
ret = models.Person.objects.all().extra(
select={"gt": "salary > 2000"}
)
相当于:
SELECT (salary > ) AS `gt`, `person`.`id`, `person`.`name`, `person`.`salary`, `person`.`dept_id` FROM `person` LIMIT ; args=()
 
直接执行原生的SQL语句,类似pymysql的用法
from django.db import connection
cursor = connection.cursor() # 获取光标,等待执行SQL语句
cursor.execute("""SELECT * from person where id = %s""", [])
row = cursor.fetchone()
print(row)
                   F查询和Q查询         
F查询
 
要对两个字段的值做比较,Django 提供 F() 来做这样的比较。
F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
.查询评论数大于收藏数的书籍
from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F('keep_num'))
.Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
models.Book.objects.filter(commnet_num__lt=F('keep_num')*)
3修改操作也可以使用F函数,比如将每一本书的价格提高30元
# 具体的对象没有update(),QuerySet对象才有update()方法
models.Book.objects.all().update(price=F("price")+)
刷单 把每一本书的卖出数都乘以3
obj = models.Book.objects.first()
obj.maichu = *
obj.save()
.给每一本书的书名后面加上 第一版
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F("title"), Value("第一版")))
 
    Q查询     
 
如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象。
from django.db.models import Q
.查询 卖出数大于1000,并且 价格小于100的所有书
ret = models.Book.objects.filter(maichu__gt=, price__lt=)
print(ret)
.查询 卖出数大于1000,或者 价格小于100的所有书
ret = models.Book.objects.filter(Q(maichu__gt=) | Q(price__lt=))
. Q查询和字段查询同时存在时, 字段查询要放在Q查询的后面
ret = models.Book.objects.filter(Q(maichu__gt=) | Q(price__lt=), title__contains="金老板")
 
Q().children查询
 
Q().children,通过字段字符串查询
q=Q()
##查询出title字段中值为go的对象
q.children.append(("title","go"))
Book.objects.filter(q)
Out[]: <QuerySet [<Book: go>]>
##查询出title字段中值含有g的对象
q.children.append(("title__contains","g"))
Book.objects.filter(q)
Out[]: <QuerySet [<Book: go>]>
q=Q() #不同的字段之间的关系默认为and
q.children.append(("title__contains","g"))
q.children.append(("price",))
Book.objects.filter(q)
Out[]: <QuerySet []>
q=Q()
q.connector="or" #不同的字段之间的关系更改为or
q.children.append(("title__contains","g"))
q.children.append(("price",))
Book.objects.filter(q)
Out[]: <QuerySet [<Book: go>]>
 

ORM单表查询,跨表查询,分组查询的更多相关文章

  1. Django 多表、跨表、聚合、分组查询

    前期准备: 创建表 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalFi ...

  2. django models的点查询/跨表查询/双下划线查询

    django models 在日常的编程中,我们需要建立数据库模型 而往往会用到表与表之间的关系,这就比单表取数据要复杂一些 在多表之间发生关系的情形下,我们如何利用models提供的API的特性获得 ...

  3. mysql 去重,跨表更新,跨表删除

    一.去重 1.查询出重复的记录 CREATE TABLE push_log_full_2013_10_30_tmp SELECT * FROM `push_log_full` WHERE time B ...

  4. MySQL-快速入门(5)数据查询-常用关键字、分组查询、聚合函数

    1.in关键字.in的效率高于or. in (value1,value2,...) 或者not in (value1,value2,...) 2.between ... and ... between ...

  5. ClickHouse 对付单表上亿条记录分组查询秒出, OLAP应用秒杀其他数据库

    1.  启动并下载一个clickhouse-server, By default, starting above server instance will be run as default user ...

  6. BBS--功能4:个人站点页面设计(ORM跨表与分组查询)

    查询: 日期归档查询 1 date_format ============date,time,datetime=========== create table t_mul_new(d date,t t ...

  7. 5 功能4:个人站点页面设计(ORM跨表与分组查询)

    1.个人站点页面文章的查询 # 个人站点 http://www.cnblogs.com/wh1520577322/ http://www.cnblogs.com/liucong12345/ http: ...

  8. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  9. Django框架(九)-- 多表操作:一对一、一对多、多对多的增删改,基于对象/双下划线的跨表查询、聚合查询、分组查询、F查询与Q查询

    一.创建多表模型 一对一:OneToOneField 一对多:ForeignKey 多对多:ManyToManyField 创建表时,会自动添加一个nid字段,并且自增,所以id可以不用手动创建 On ...

  10. django orm 基于双下划线的跨表查询

    一..基于双下划线的跨表查询(join实现) key:正向查询按字段,反向查询按表明小写 1.一对多跨表查询 查询在跨表中可以有两种方式,正向查询就是关键字段在你要搜索的表,没有关键字段就是反向查询 ...

随机推荐

  1. 创建 GPG 证书

    一.什么是 GPG 以下引自维基百科: GNU Privacy Guard(GnuPG或GPG)是一种加密软件,它是PGP加密软件的满足GPL的替代物.GnuPG依照由IETF订定的OpenPGP技术 ...

  2. PM2.5如何引发心脏病的?

    过去的几十年里,科学家们一点一滴地积累起关于空气污染如何威胁人类健康的新认识.他们的注意力大多集中在肺部疾病,包括癌症上面.对空气污染具体危害的认识越来越多,但是对污染的控制和治理却显得举步维艰.面对 ...

  3. Koa 学习

    中间件引擎 1234567891011121314151617181920212223242526272829303132333435363738 const Koa = require('koa') ...

  4. java.lang.SecurityException: class "javax.servlet.AsyncContext"'s signer information does not match signer information of other classes in the same package

    最近在写个Http协议的压测挡板时,遇到以下错误. 2018-03-08 10:34:07.808:INFO:oejs.Server:jetty-8.1.9.v20130131 2018-03-08 ...

  5. dubbo与trivial超时机制的深入思考

    说在前面 trivial是根据之前设计的RPC框架而来的(还在增进当中),其中较为不同的一个点为,在客户端去掉了业务线程池,因为既然都要等待,不必要再加一层. 进入正题 有在网上看到这样的信息,“之前 ...

  6. 在idea下遇到的问题汇总(间接性更新)

    在idea下遇到的问题汇总(间接性更新) tomcat下的jsp代码问题: 在idea的环境下,遇到jsp代码.符号失效,首先需要考虑到jar包没有引入,情况如图: 这种情况是因为jar包没有导入进去 ...

  7. go语言指南之切片练习

    题目: 实现 Pic.它应当返回一个长度为 dy 的切片,其中每个元素是一个长度为 dx,元素类型为 uint8 的切片.当你运行此程序时,它会将每个整数解释为灰度值(好吧,其实是蓝度值)并显示它所对 ...

  8. 利用机器学习检测HTTP恶意外连流量

    本文通过使用机器学习算法来检测HTTP的恶意外连流量,算法通过学习恶意样本间的相似性将各个恶意家族的恶意流量聚类为不同的模板.并可以通过模板发现未知的恶意流量.实验显示算法有较好的检测率和泛化能力. ...

  9. AE脚本:把SubRip/SRT/TXT/VTT字幕导入到AE

    脚本介绍 如果您需要在视频中嵌入字幕以进行网络或磁带传送,那么这个脚本则非常有用.可以将SubRip/SRT/TXT/VTT字幕格式文件通过 pt_ImportSubtitles脚本直接加载到AE软件 ...

  10. 前端每日实战:113# 视频演示如何用纯 CSS 创作一个赛车 loader

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/mGdXGJ 可交互视频 此视频是可 ...