2009-05-31 5 views
3

を使用して、最大値に基づいて、単一の子行をフェッチ:私は別のモデル、「契約」への1対多の関係を持っているモデル、「市場」を持っているDjangoのORM

class Market(models.Model): 
    name = ... 
    ... 

class Contract(models.Model): 
    name= ... 
    market = models.ForeignKey(Market, ...) 
    current_price = ... 

私は思います市場のオブジェクトを最大価格で契約と一緒に取り出すのが好きです。これは私が生のSQLを経由してそれを行うだろうかです:SQLを使用せずにこれを実装する方法は

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 

ありますか?存在する場合、どちらがパフォーマンスの面で好ましいべきですか?

答えて

9

Django 1.1(現在のベータ版)では、データベースAPIにaggregationのサポートが追加されています。あなたのクエリは次のように行うことができます(あなたのクエリのように行います)

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) 

APIは、余分なサブクエリの代わりに参加を使用しています。

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() 

これは、次のSQLクエリが生成されます。特にデータベースシステムを知らなくても、どのクエリが高速かを判断するのは難しいです。ベンチマークをして決定することをお勧めします。

+0

私はサブクエリが2つのジョインよりも効率的だと想定していましたが、あなたはそれが仮定されるべきではないということです。それをベンチマークして見てください。 –

+0

アイマン、ありがとう! Djangoの初心者の方は、それを動作させるのにはしばらく時間がかかりました:)私は、この文のフィルタについて質問しました。複数の契約の価格が等しい-unlikely-イベントの可能性があります。そうであれば、クエリはそれらをすべてフェッチし、市場に複数の契約を与えるでしょうか? – shanyu

+0

@ozgur - 実際には、2つの契約の価格が同じ場合(最大の場合もあります)、両方の契約が返されます。 –

関連する問題