Doctrine DQL中的联接子查询

4
我希望使用DQL创建一个类似SQL的查询:
select
    e.*
from
    e
inner join (
    select
        uuid, max(locale) as locale
    from
        e
    where
        locale = 'nl_NL' or
        locale = 'nl'
    group by
        uuid
) as e_ on e.uuid = e_.uuid and e.locale = e_.locale

我尝试使用QueryBuilder来生成查询和子查询。我认为它们本身做得很好,但我无法在联接语句中将它们组合起来。有人知道在DQL中是否可能吗?我不能使用本地SQL,因为我想返回真实的对象,并且我不知道为哪个对象运行此查询(我只知道具有uuid和locale属性的基类)。

    $subQueryBuilder = $this->_em->createQueryBuilder();
    $subQueryBuilder
        ->addSelect('e.uuid, max(e.locale) as locale')
        ->from($this->_entityName, 'e')
        ->where($subQueryBuilder->expr()->in('e.locale', $localeCriteria))
        ->groupBy('e.uuid');

    $queryBuilder = $this->_em->createQueryBuilder();
    $queryBuilder
        ->addSelect('e')
        ->from($this->_entityName, 'e')
        ->join('('.$subQueryBuilder.') as', 'e_')
        ->where('e.uuid = e_.uuid')
        ->andWhere('e.locale = e_.locale');

在子查询上执行INNER JOIN正是我想要做的事情。你找到解决方案了吗? - Chadwick Meyer
1个回答

0

你不能在DQL的FROM子句中放置子查询。

根据与你在IRC上的讨论,我将假设你的主键是{uuid, locale}。由于你的查询中还有两个不同的列,这可能会变得很丑陋。 你可以将它放入WHERE子句中:

select
    e
from
    MyEntity e
WHERE
    e.uuid IN (
        select
            e2.uuid
        from
            MyEntity e2
        where
            e2.locale IN (:selectedLocales)
        group by
            e2.uuid
    )
    AND e.locale IN (
        select
            max(e3.locale) as locale
        from
            MyEntity e3
        where
            e3.locale IN (:selectedLocales)
        group by
            e3.uuid
    )

请注意,我使用了与你绑定到:selectedLocales 的(非空)语言环境数组进行比较。这是为了避免破坏查询缓存,如果您想匹配其他语言环境,则需要使用该方法。
如果没有实际优势,我也不建议使用查询生成器来构建此操作,因为如果您动态添加条件,则会更容易破坏查询缓存(而且涉及3个查询生成器!)

我认为这不会起作用,因为结果中每行的uuid和locale之间没有关联。 - Martijn de Munnik
是的,你说得对...这样做不会真正起作用。可能可以将“uuid”和“locale”字段“concat”,然后进行检查,但在这种情况下任何密钥都将无用(而且这甚至不是一个好方法)。 - Ocramius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接