DQL选择具有一列MAX值的每一行

时间:2015-04-30 08:29:04

标签: php sql-server symfony doctrine-orm greatest-n-per-group

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

现在,我在两个查询中执行此操作:

  • 一个用于获取表格中列的最大值
  • 然后我选择具有此值的行。

我确定可以通过一个查询完成此操作。

正在搜索,我在this answer中找到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语法。

THX!

3 个答案:

答案 0 :(得分:4)

经过几个小时的头痛和谷歌搜索以及stackOverflow读数...... 我终于找到了如何制作它。

这是我的最终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();

答案 1 :(得分:0)

当我试图制作一个子查询时,对我来说:

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

答案 2 :(得分:0)

要使用纯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

以上内容将返回每组最大记录数(每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

这里我假设表中可以有多个条目,例如(MontantMarche),每个affaire,所以我在这里尝试在affaire上进行自我加入,另一个在加入的调整是我正在尝试只加入来自右表(b)的行,其中的periodeComptable&lt; b的periodeComptable,因此左表(a)的行periodeComptable的行将从右表(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

希望它有意义