Вложенные SQL запросы в Django

Вложенные SQL запросы в Django

Вы знали, что Django ORM умеет делать вложенные SQL запросы? К своему стыду я узнал это не так давно.

Допустим, у нас есть такие модели питомника (Nursery) и питомца (Pet):

class Nursery(models.Model):
    title = models.CharField(max_length=50)

class Pet(models.Model):
    name = models.CharField(max_length=50)
    nursery = models.ForeignKey(Nursery, related_name='pets')

Нам нужно получить всех питомцев (Pet), которые находятся в заданных питомниках (Nursery). Например в питомниках, title который начинается с "Moscow":

nurseries = Nursery.objects.filter(title__startswith="Moscow")
Pet.objects.filter(nursery__in=nurseries)

Эти строчки сделают лишь один запрос к базе данных, в котором будет вложенный запрос :

SELECT "users_pet"."id", "users_pet"."name", "users_pet"."nursery_id" FROM "users_pet" WHERE "users_pet"."nursery_id" IN (SELECT "users_nursery"."id" FROM "users_nursery" WHERE "users_nursery"."title" LIKE Moscow%)

Однако, следует иметь в виду, что хотя выполняется один запрос к БД, это не всегда означает лучшую производительность. Тут все зависит от выбранной базы данных. Например, как советуют в документации django, в случае MySQL более эффективно выполнить два запроса вместо одного, т.к. эта БД не всегда хорошо оптимизирует вложенные запросы.

Т.е. для MySQL такой код будет эффективнее (судя по докам django):

nurseries = Nursery.objects.filter(title__startswith="Moscow").values_list('pk', flat=True)
Pet.objects.filter(nursery__in=list(nurseries))

несмотря на то, что выполнится два запроса:

SELECT "users_nursery"."id" FROM "users_nursery" WHERE "users_nursery"."title" LIKE Moscow%
SELECT "users_pet"."id", "users_pet"."name", "users_pet"."nursery_id" FROM "users_pet" WHERE "users_pet"."nursery_id" IN (1, 2)

Опубликовано: Сен. 9, 2014
Bookmark and Share
Comments powered by Disqus