linha única criança atraente com base em um valor máximo usando Django ORM
-
06-09-2019 - |
Pergunta
Eu tenho um modelo, "Mercado", que tem uma relação de um-para-muitos para outro modelo, "Contrato":
class Market(models.Model):
name = ...
...
class Contract(models.Model):
name= ...
market = models.ForeignKey(Market, ...)
current_price = ...
Eu gostaria de buscar objetos mercado, juntamente com o contrato com o preço máximo de cada um. Isto é como eu faria isso via SQL cru:
SELECT M.id as market_id, M.name as market_name, C.name as contract_name, C.price
as price from pm_core_market M INNER JOIN
(SELECT market_id, id, name, MAX(current_price) as price
FROM pm_core_contract GROUP BY market_id) AS C
ON M.id = C.market_id
Existe uma maneira de implementar isso sem usar SQL? Se houver, qual deve ser preferido em termos de desempenho?
Solução
Django 1.1 (atualmente beta) adiciona agregação apoio ao API de banco de dados. Sua consulta pode ser feito assim:
from django.db.models import Max, F
Contract.objects.annotate(max_price=Max('market__contract__current_price')).filter(current_price=F('max_price')).select_related()
Isso gera a seguinte consulta SQL:
SELECT contract.id, contract.name, contract.market_id, contract.current_price, MAX(T3.current_price) AS max_price, market.id, market.name
FROM contract LEFT OUTER JOIN market ON (contract.market_id = market.id) LEFT OUTER JOIN contract T3 ON (market.id = T3.market_id)
GROUP BY contract.id, contract.name, contract.market_id, contract.current_price, market.id, market.name
HAVING contract.current_price = MAX(T3.current_price)
A API usa um extra de associação em vez de uma subconsulta (como sua consulta faz). É difícil dizer qual consulta é mais rápido, especialmente sem saber o sistema de banco de dados. Eu sugiro que você faça algumas referências e decidir.