2011-10-29 3 views
3

가입 :교리 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 속성을 추가하지 않고, 교리 DQL이 작업을 수행하는 것이 가능하고, 도메인을 complexify 필요 모델 쓸데없이? 나는 하나의 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을 훨씬 빠르게)에만 조인 좋아, 나는 마침내 그것을 할 수있는 방법을 발견
+0

감사합니다. 그러나 성능에 대한 몇 가지 우려 사항이 있습니다. MySQL 5.6.3 m6을 실행 중입니다.이 하위 쿼리는 여전히 JOIN으로 재 작성되지 않으며, 이러한 쿼리에 직면했을 때 속도가 크게 떨어집니다. 가장 효율적인 해결책은 적절한 JOIN을 수행하는'ZoneRestaurants' 뷰를 생성 한 다음, 클래스에 사용되지 않는 "fake"('가짜 ')'$ restaurants' 속성을 존에 포함시키고,이 속성을'@ ManyToMany'로 매핑하는 것입니다. ZoneRestaurants보기를 junction 테이블로 사용합니다. – Benjamin