DQL Select 每行有一列的最大值

DQL Select every rows having one column's MAX value

使用 Symfony 2 和 Doctrine,我正在寻找一种方法 select 每行在特定列中具有最大值。

现在,我在两个查询中这样做:

我相信这可以通过一个查询来完成。

正在搜索,我找到了 this answer in a thread,这似乎是我要搜索的内容,但是在 SQL.

所以根据答案的第一个解决方案,我要构建的查询应该是这样的:

select yt.id, yt.rev, yt.contents
from YourTable yt
inner join(
    select id, max(rev) rev
    from YourTable
    group by id
) ss on yt.id = ss.id and yt.rev = ss.rev

有人知道如何在 Doctrine DQL 中制作吗?

现在,这是我的测试代码(不工作):

$qb2= $this->createQueryBuilder('ms')
            ->select('ms, MAX(m.periodeComptable) maxPeriode')
            ->where('ms.affaire = :affaire')
            ->setParameter('affaire', $affaire);

$qb = $this->createQueryBuilder('m')
            ->select('m')
            //->where('m.periodeComptable = maxPeriode')

            // This is what I thought was the most logical way of doing it:
            ->innerJoin('GAAffairesBundle:MontantMarche mm, MAX(mm.periodeComptable) maxPeriode', 'mm', 'WITH', 'm.periodeComptable = mm.maxPeriode')

            // This is a version trying with another query ($qb2) as subquery, which would be the better way of doing it for me,
            // as I am already using this subquery elsewhere
            //->innerJoin($qb2->getDQL(), 'sub', 'WITH', 'm.periodeComptable = sub.maxPeriode')

            // Another weird try mixing DQL and SQL logic :/
            //->innerJoin('SELECT MontantMarche mm, MAX(mm.periodeComptable) maxPeriode ON m.periodeComptable = mm.maxPeriode', 'sub')

            //->groupBy('m')
            ->andWhere('m.affaire = :affaire')
            ->setParameter('affaire', $affaire);

    return $qb->getQuery()->getResult();

实体是GAAffairesBundle:MontantMarche,所以这段代码是在对应仓库的一个方法中。

更一般地说,我正在学习如何处理子查询(SQL 和 DQL)和高级查询的 DQL 语法。

谢谢!

对我来说,当我尝试创建一个子查询时:

->andWhere($qb->expr()->eq('affaire', $qb2->getDql()));

经过几个小时的头痛、谷歌搜索和 Whosebug 读数... 我终于知道怎么做了。

这是我最终的 DQL queryBuilder 代码:

    $qb = $this->createQueryBuilder('a');
    $qb2= $this->createQueryBuilder('mss')
            ->select('MAX(mss.periodeComptable) maxPeriode')
            ->where('mss.affaire = a')
            ;

    $qb ->innerJoin('GAAffairesBundle:MontantMarche', 'm', 'WITH', $qb->expr()->eq( 'm.periodeComptable', '('.$qb2->getDQL().')' ))
        ->where('a = :affaire')
        ->setParameter('affaire', $affaire)
        ;

    return $qb->getQuery()->getResult();

要使用纯 DQL 实现此目的而不使用任何聚合函数,您可以将学说查询编写为

SELECT a
FROM GAAffairesBundle:MontantMarche a
    LEFT JOIN GAAffairesBundle:MontantMarche b
    WITH a.affaire = b.affaire 
    AND a.periodeComptable < b.periodeComptable
WHERE b.affaire IS NULL
ORDER BY a.periodeComptable DESC

以上将 return 您每组的最大记录数(每个 affaire

Expalnation

以上 DQL 的等效 SQL 将类似于

SELECT a.*
FROM MontantMarche a
LEFT JOIN MontantMarche b 
    ON a.affaire = b.affaire 
    AND a.periodeComptable < b.periodeComptable
WHERE b.affaire IS NULL
ORDER BY a.periodeComptable DESC

这里我假设 table 中可以有多个条目,例如每个 affaire 的(MontantMarche),所以我在这里尝试在 affaire 上进行自连接和另一个调整在 join 中,我试图仅从右边 table(b) 加入行,其中 a's periodeComptable < b's periodeComptable,所以左边的行 table (a) 最高 periodeComptable 将从右边 table(b) 开始有一个空行,因此根据 affaire 选择最高的行 WHERE right table row IS NULL 是必要的。

类似地,将您发布的示例查询与内部联接一起使用可以写成

select yt.id, yt.rev, yt.contents
from YourTable yt
left join YourTable ss on yt.id = ss.id and yt.rev < ss.rev
where ss.rev is null

希望它有意义