Django ORM Оптимизация запросов к БД
У меня есть запрос, состоящий из двух обращений к БД.
первый из которых содержит 'aggregate' - поэтому он выполняется немедленно.
Я хочу знать, могу ли я сократить его до одного DB hit.
Запрос следующий:
"Найти клиентов, чьи идентификационные номера больше, чем идентификационные номера всех клиентов Техаса."
Двумя наборами запросов являются:
highest_tx_id = Customer.objects.filter(state='TX').aggregate(Max('id'))
res = Customer.objects.filter(id__gt=highest_tx_id['id_max'])
Добавление примера:
>>> reset_queries()
>>> highest_tx_id = Customer.objects.filter(state='TX').aggregate(Max('id'))
>>> res = Customer.objects.filter(id__gt=highest_tx_id['id__max'])
>>> connection.queries
[{'sql': 'SELECT MAX("customer"."id") AS "id__max" FROM "customer" WHERE "customer"."state" = \'TX\'', 'time': '0.001'}]
>>> res
<QuerySet [<Customer: Customer object (550)>, <Customer: Customer object (551)>, <Customer: Customer object (552)>, <Customer: Customer object (553)>, <Customer: Customer object (555)>, <Customer: Customer object (661)>, <Customer: Customer object (665)>]>
>>> connection.queries
[{'sql': 'SELECT MAX("customer"."id") AS "id__max" FROM "customer" WHERE "customer"."state" = \'TX\'', 'time': '0.001'}, {'sql': 'SELECT "customer"."id", "customer"."fname", "customer"."lname", "customer"."address", "customer"."city", "customer"."state", "customer"."zip_code", "customer"."phone", "customer"."company_name" FROM "customer" WHERE "customer"."id" > 444 LIMIT 21', 'time': '0.001'}]
>>>
Есть ли способ делать такие запросы, используя 1 удар по БД?
Вы можете попробовать использовать Subquery.
from django.db.models import Subquery
highest_tx_id = Customer.objects.filter(state='TX').aggregate(Max('id'))['id__max']
res = Customer.objects.filter(id__gt=Subquery(highest_tx_id))
Развивая ответ @TaipanRex, вы можете сделать что-то вроде этого:
from django.db.models import Subquery
highest_tx_id = Customer.objects.filter(state='TX').order_by('-id').values('id')[:1]
res = Customer.objects.filter(id__gt=Subquery(highest_tx_id))