作为described in a related question,我有一个ViewVersion
实体,其中包含给定View
的多个版本。如果我想获取基于哪个是最后修改的“最佳”viewVersions列表,您可以不执行GROUP BY viewId
,因为您无法控制这些返回的顺序(例如timeMod DESC)。因此,经过几天的搜索,我相信最好的方法是通过一个简单的INNER JOIN本身匹配最高的timeMod。
这在MySQL中运行得很好,但是你在Doctrine中可以做到这一点吗?
SELECT view_version.*
FROM view_version
#inner join only returns where the result sets overlap, i.e. the one record with highest timeMod
INNER JOIN (
SELECT MAX(timeMod) maxTimeMod, viewId
FROM view_version
GROUP BY viewId
) version ON version.viewId = view_version.viewId AND view_version.timeMod = version.maxTimeMod
#join other tables for filter, etc
INNER JOIN view ON view.id = view_version.viewId
INNER JOIN content_type ON content_type.id = view.contentTypeId
WHERE view_version.siteId=1
AND view.contentTypeId IN (2)
ORDER BY view_version.title ASC
如何使用QueryBuilder或DQL(或绝对必要的Native)形成Doctrine查询以加入实体TO ITSELF。
每次尝试时,INNER JOIN
都会抱怨SELECT语句:
QueryException: [Semantical Error] line 0, col 72 near '(SELECT': Error: Class '(' is not defined
注意 :这与我原来的问题不同,因为它专注于将实体加入自身。
答案 0 :(得分:0)
要回答具体说明的问题,您可以轻松地将任何实体加入其自身(即使它没有自引用关联),只需加入实体快捷方式名称(而不是像正常一样的关联字段名称)
$viewVersionRepo = $em->getRepository('GutensiteCmsBundle:View\ViewVersion');
$queryBuilder = $viewVersionRepo->createQueryBuilder('e')
// JOIN ENTITY TO ITSELF - VIA BUNDLE SHORTCUT NAME
->join('GutensiteCmsBundle:View\ViewVersion', 'version', 'WITH', 'e.viewId = version.viewId')
// JOIN OTHER ASSOCIATED ENTITIES - VIA FIELD NAME
->join('e.view', 'view')
->addSelect('view')
->join('view.contentType', 'contentType')
->addSelect('contentType')
// PERFORM RANDOM FILTERS
->andWhere('e.siteId = :siteId')->setParameter('siteId', 1)
->addOrderBy('e.title', 'ASC');
$query = $queryBuilder->getQuery();
$results = $query->getResult();
然而,这是 NOT 完成与问题中的查询相同的事情。它不是从select语句加入临时表,这是本例所需的(以及引用的另一个问题)。此处没有MAX列连接,因为您无法对连接进行GROUP。您可以通过JOINED表中的一列对主查询进行GROUP,但这并不能让您在JOIN的ON / WITH部分执行MAX。
但希望这个答案至少对其他想知道如何将实体加入自身或任何随机实体的人有所帮助。