2011-10-29 10 views
3

のJOIN:教義DQLは、私は、次のエンティティは<a href="http://www.doctrine-project.org/projects/orm/2.1/docs/hu" rel="nofollow">Doctrine 2</a>にマッピングされている

class Zone 
{ 
    /** 
    * @ManyToOne(targetEntity="Zone", inversedBy="children") 
    * @var Zone 
    */ 
    protected $parent; 

    /** 
    * @OneToMany(targetEntity="Zone", mappedBy="parent") 
    * @var Zone[] 
    */ 
    protected $children; 

    /** 
    * @ManyToMany(targetEntity="Zone") 
    * @var Zone[] 
    */ 
    protected $descendants; 
} 

class Restaurant 
{ 
    /** 
    * @ManyToOne(targetEntity="Zone") 
    * @var Zone 
    */ 
    protected $zone; 
} 

基本的には、ゾーンは子供を親を有するため。子供たちは子供たちを持つかもしれないので、各ゾーンにはすべての子孫のリストも保持されます。

各レストランにはゾーンが割り当てられています。

私がしたいことは、DQL JOINを実行して、特定のゾーン(そのすべての子孫を含む)のすべてのレストランを返すことです。

私は、プレーンSQLでこれをしなければならなかった場合は、私が書くでしょう:

SELECT r.* from Zone z 
JOIN ZoneDescendant d ON d.zoneId = z.id 
JOIN Restaurant r ON r.zoneId = d.descendantId 
WHERE z.id = ?; 

ゾーンに$restaurantsプロパティを追加して、ドメインをcomplexifyすることなく、教義DQLでこれを行うには、それが可能ですモデルは役に立たない?私は、単一のDQLクエリでこれを行うと考えることができ

答えて

8

SELECT r 
FROM Restaurant r, 
    Zone z 
JOIN z.descendants d 
WHERE r.zone = d 
AND z = ?1; 
+1

ええ、それはずっと良い、あなたがより良い解決を見つけてうれしい!良いアイデア :) – Diego

1

唯一の方法は、サブクエリを使用することです:

SELECT r FROM Restaurant r WHERE r.zone IN (SELECT zc.id FROM r.zone z JOIN z.children zc WHERE z.id = :zoneId) OR r.zone = :zoneId 
(MySQLの上でかなり速く)結合のみで[OK]を、私は最終的にそれを行うための方法を見つけ
+0

このアイデアは、ありがとうございます!しかし、私はパフォーマンスに関するいくつかの懸念があります。私はMySQL 5.6.3 m6を実行していますが、これらのサブクエリはJOINとして書き換えられず、これらのクエリに直面すると大幅に減速します。私は、最も効率的な解決策は、適切なJOINを実行する 'ZoneRestaurants'ビューを作成し、ゾーン内に' $ restaurant'プロパティーを(クラスで使われていない)「偽」し、 '@ ManyToMany'としてこのプロパティーをマップすることですジャンクション・テーブルとしてZoneRestaurantsビューを使用します。 – Benjamin

関連する問題

 関連する問題