的发生LEFT OUTER JOIN
本身是否是一个问题,我不能说,但是,无论如何,注意这些外部连接在哪些情况下实际发生可能会很有趣。
这是一个天真的尝试,使用一些示例查询来说明上述内容。
假设我们有一些使用多表继承的模型如下:
from django.db import models
class Parent(models.Model):
parent_field = models.CharField(max_length=10)
class ChildOne(Parent):
child_one_field = models.CharField(max_length=10)
class ChildTwo(Parent):
child_two_field = models.CharField(max_length=10)
默认情况下,子实例获取 aparent_ptr
并且父实例可以使用childone
or访问子对象(如果它们存在) childtwo
。请注意,它parent_ptr
表示用作主键的一对一关系(实际的子表没有id
列)。
Django
这是一个带有一些简单查询示例的快速而简单的单元测试,显示了INNER JOIN
和OUTER JOIN
中的相应出现次数SQL
:
import re
from django.test import TestCase
from inheritance.models import (Parent, ChildOne, ChildTwo)
def count_joins(query, inner_outer):
""" Count the occurrences of JOIN in the query """
return len(re.findall('{} join'.format(inner_outer), str(query).lower()))
class TestMultiTableInheritance(TestCase):
def test_queries(self):
# get children (with parent info)
query = ChildOne.objects.all().query
self.assertEqual(1, count_joins(query, 'inner'))
self.assertEqual(0, count_joins(query, 'outer'))
# get parents
query = Parent.objects.all().query
self.assertEqual(0, count_joins(query, 'inner'))
self.assertEqual(0, count_joins(query, 'outer'))
# filter children by parent field
query = ChildOne.objects.filter(parent_field=parent_value).query
self.assertEqual(1, count_joins(query, 'inner'))
self.assertEqual(0, count_joins(query, 'outer'))
# filter parents by child field
query = Parent.objects.filter(childone__child_one_field=child_value).query
self.assertEqual(1, count_joins(query, 'inner'))
self.assertEqual(0, count_joins(query, 'outer'))
# get child field values via parent
query = Parent.objects.values_list('childone__child_one_field').query
self.assertEqual(0, count_joins(query, 'inner'))
self.assertEqual(1, count_joins(query, 'outer'))
# get multiple child field values via parent
query = Parent.objects.values_list('childone__child_one_field',
'childtwo__child_two_field').query
self.assertEqual(0, count_joins(query, 'inner'))
self.assertEqual(2, count_joins(query, 'outer'))
# get child-two field value from child-one, through parent
query = ChildOne.objects.values_list('parent_ptr__childtwo__child_two_field').query
self.assertEqual(1, count_joins(query, 'inner'))
self.assertEqual(1, count_joins(query, 'outer'))
# get parent field value from parent, but through child
query = Parent.objects.values_list('childone__parent_field').query
self.assertEqual(0, count_joins(query, 'inner'))
self.assertEqual(2, count_joins(query, 'outer'))
# filter parents by parent field, but through child
query = Parent.objects.filter(childone__parent_field=parent_value).query
self.assertEqual(2, count_joins(query, 'inner'))
self.assertEqual(0, count_joins(query, 'outer'))
请注意,并非所有这些查询都有意义:它们仅用于说明目的。
另请注意,此测试代码不是 DRY,但这是故意的。