il recupero di fila singolo bambino sulla base di un valore massimo utilizzando Django ORM
-
06-09-2019 - |
Domanda
Ho un modello, "mercato", che ha una relazione uno-a-molti per un altro modello, "Contratto":
class Market(models.Model):
name = ...
...
class Contract(models.Model):
name= ...
market = models.ForeignKey(Market, ...)
current_price = ...
Mi piacerebbe andare a prendere oggetti di mercato insieme con il contratto con il prezzo massimo di ciascuna. Questo è come mi piacerebbe farlo tramite SQL prime:
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
C'è un modo per implementare questo senza usare SQL? Se c'è, quale dovrebbe essere preferito in termini di prestazioni?
Soluzione
Django 1.1 (attualmente in beta) aggiunge aggregazione sostegno alla Database API. La query può essere fatto in questo modo:
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()
Questo genera la seguente query 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)
L'API utilizza un extra join invece di una sottoquery (come la query fa). E 'difficile dire quale query è più veloce, soprattutto senza conoscere il sistema di database. Io suggerisco di fare alcuni parametri di riferimento e decidere.