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

Posted

技术标签:

【中文标题】DQL选择具有一列MAX值的每一行【英文标题】:DQL Select every rows having one column's MAX value 【发布时间】:2015-04-30 08:29:03 【问题描述】:

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

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

一个获取表中列的最大值 然后我选择具有该值的行。

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

搜索,我在a thread 中找到了this answer,这似乎是我要搜索的内容,但在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();

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

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

谢谢!

【问题讨论】:

Doctrine Query Language get Max/Latest Row Per Group的可能重复 这不是另一个线程的副本。首先是因为我的帖子是在将近 3 年前发布的(这会使另一个可能重复),并且因为在我的情况下,我正在搜索连接元素的选择(具有字段的最大值),而在另一个线程上,作者似乎是在直接搜索具有字段最大值的元素的选择,其中每组具有相同名称的元素。 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

对我来说,当我尝试进行子查询时:

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

【讨论】:

谢谢@Charlie Lucas,但这对我没有帮助。 @Cedo 也许这就是你需要的加入 不,我有一个 DQL 语法错误类型“SELECT 不是一个类...”。所以整个查询语法不正确。【参考方案3】:

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

解释

上述 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

这里我假设每个affaire 表中可以有多个条目,例如(MontantMarche),所以在这里我尝试在affaire 上进行自联接,而联接中的另一个调整是我试图只加入行来自右表(b),其中 a 的 periodeComptable (a) 的最高行 periodeComptable 将有来自右表(b) 的空行,因此每个 affaire 选择最高行 @ 987654331@ 必要。

类似地使用您发布的带有内部连接的示例查询可以写成

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

希望有意义

【讨论】:

哈立德您好,感谢您的回答,对我的延误表示歉意。这很有趣。不过有点奇怪。你能解释一下这里的逻辑吗? (你是怎么找到那个的??)我很好奇 b.periodeComptable where b.affaire IS NULL 的值是什么。当我们要求 a.affaire = 的元素时,这怎么能返回任何东西b.affaire 和 b.affaire 为空?因为没有任何元素(montantMarche)具有事务 NULL。另外,我认为您在这里遗漏了要点:我正在从特定事件中搜索所有“***”元素(montantMarches).. 您似乎没有在查询中绑定任何事务.id。 @Cedo 我已经更新了我的答案,以澄清 DQL 及其等效 SQL 的作用,为了更好地理解,您可以为您的表结构提供示例数据,以便我可以使用您的示例数据集添加详细信息跨度>

以上是关于DQL选择具有一列MAX值的每一行的主要内容,如果未能解决你的问题,请参考以下文章

SQL:如何为一列中具有重复值的每组行选择一行?

SQL / Hive 选择具有特定列值的第一行

为没有子查询的已知其他几列选择具有 MAX(column) 的一行

按列分组并选择具有多个最小值的行中的所有字段

选择具有 MAX 值的记录

如何仅在列更改其值的情况下选择行(从第一行到最后一行)?