Php DQL连接原则

Php DQL连接原则,php,join,orm,doctrine-orm,dql,Php,Join,Orm,Doctrine Orm,Dql,我已将以下实体映射为: 基本上,一个区域有父对象,因此有子对象。因为子对象本身可能有子对象,所以每个区域也保留其所有子对象的列表 每个餐厅都有一个区域 我想做的是执行DQL联接,以返回特定区域中的所有餐馆(包括其所有子代) 如果我必须用纯SQL来实现这一点,我会写: SELECT r.* from Zone z JOIN ZoneDescendant d ON d.zoneId = z.id JOIN Restaurant r ON r.zoneId = d.descendantId WHERE

我已将以下实体映射为:

基本上,一个区域有父对象,因此有子对象。因为子对象本身可能有子对象,所以每个区域也保留其所有子对象的列表

每个餐厅都有一个区域

我想做的是执行DQL联接,以返回特定区域中的所有餐馆(包括其所有子代)

如果我必须用纯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 = ?;

使用Doctrine DQL是否可以做到这一点,而无需在区域上添加
$restaurants
属性,也无需无用地复杂化域模型?

在单个DQL查询中实现这一点的唯一方法是使用子查询:

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上要快得多):


这个主意行得通,谢谢!但是,我对性能有一些担忧。我运行的是MySQL 5.6.3 m6,它仍然不会将这些子查询重写为联接,并且在遇到这些查询时速度会急剧降低。我认为最有效的解决方案可能是创建一个执行适当联接的
ZoneRestaurants
视图,然后在该区域中包含一个“fake”(在类中未使用)
$restaurants
属性,并使用ZoneRestaurants视图作为连接表将该属性映射为
@ManyToMany
。是的,这样更好,很高兴你找到了更好的解决方案!好主意:)
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
SELECT r
FROM Restaurant r,
     Zone z
JOIN z.descendants d
WHERE r.zone = d
AND z = ?1;