Django ORM 模型 class Base(models.Model): set_null = { 'null': True, 'blank': True } set_fk = { 'db_constraint': False, 'on_delete': models.SET_NULL } set_mtm = { 'db_constraint': False, } class Meta: abstract = Trueclass Student(Base): n
Django ORM 模型
class Base(models.Model): set_null = { 'null': True, 'blank': True } set_fk = { 'db_constraint': False, 'on_delete': models.SET_NULL } set_mtm = { 'db_constraint': False, } class Meta: abstract = True class Student(Base): name = models.CharField(max_length=10, **Base.set_null) age = models.IntegerField(**Base.set_null) classes = models.ManyToManyField('Class', related_name='student_class', **Base.set_mtm) class Meta: db_name = 'student' class Class(Base): name = models.CharField(max_length=10, **Base.set_null) class Meta: db_name = 'classes' class Middle(Base): category = models.CharField(max_length=10, **Base.set_null) name = models.CharField(max_length=10, **Base.set_null) value = models.CharField(max_length=10, **Base.set_null) class Meta: db_table = 'tb_middle' class A(Base): model = models.ForeignKey( 'Middle', related_name='a_model', **Base.set_fk, **Base.set_null ) class Meta: db_table = 'tb_a'sql 中 where 使用
SELECT name FROM student WHERE age > 18;在执行这条 SQL 语句的时候,DBMS 会扫描 student 表中的每一条记录,然后把符合 age 大于 18 这个条件的所有记录筛选出来,并放到结果集里面去。也就是说 WHERE 关键字的作用就是判断后面的逻辑表达式的值是否为 True。如果为 True,则将当前这条记录(经过 SELECT 关键字处理后)放到结果集里面去,如果逻辑表达式的值为 False 则不放。
sql 中的 exists
有个哥们讲的很适合初学者
概念:EXISTS 运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False。
执行流程:先执行子查询,得到一个集合(或值),然后将这个集合(或值)作为一个常量带入到父查询的 WHERE 子句中去。
案例
查询选择课程是语文课程的所有学生名称
SELECT "app1_student"."name" FROM "app1_student" WHERE EXISTS ( SELECT U0."id", U0."name" FROM "app1_class" U0 INNER JOIN "app1_student_classes" U1 ON ( U0."id" = U1."class_id" ) WHERE ( U0."name" = 语文 AND U1."student_id" = "app1_student"."id" ) )django 中 exists
官方文档
官方描述:Exists 是一个 Subquery 子类,它使用 SQL EXISTS 语句。在许多情况下,它的性能比子查询更好,因为当找到第一条匹配的记录时,数据库能够停止对子查询的执行。
案例一
上面的案例 Django 中可以这样写
# 方法一 原生sql 见上 queryset = Student.objects.filter(Exists(Class.objects.filter(student_class=OuterRef('pk'), name='语文'))).values('name') # 方法二 queryset = Student.objects.filter(classes__name='语文').values('name')方法二 sql
SELECT "app1_student"."name" FROM "app1_student" INNER JOIN "app1_student_classes" ON ( "app1_student"."id" = "app1_student_classes"."student_id" ) INNER JOIN "app1_class" ON ( "app1_student_classes"."class_id" = "app1_class"."id" ) WHERE "app1_class"."name" = 语文根据真实情况选择不同查询方式。遵循尽可能使用一次数据库交互数据数据。
案例二
获取 tb_middle 中 category 为 a_model 且排除已经和tb_a 表存在关联的表 tb_middle 字段 name value的数据
思路
- 查询表 tb_middle 已经被使用的数据
- filter中过滤掉被使用的数据
达到了效果,却需要查询两次数据库。而且,在书写python比较繁琐
Middle.objects.filter(category=category).filter( ~Exists(A.objects.filter(model=OuterRef('pk'))) ) # Exists 存在 | ~Exists 不存在下次更新 annotate subquery 使用方法...