如何在Doctrine 2中按计数排序?

18

我试图按照一个字段(年份)对实体进行分组,并统计其数量。

代码:

public function countYear()
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb->select('b.year, COUNT(b.id)')
        ->from('\My\Entity\Album', 'b')
        ->where('b.year IS NOT NULL')
        ->addOrderBy('sclr1', 'DESC')
        ->addGroupBy('b.year');
    $query = $qb->getQuery();
    die($query->getSQL());
    $result = $query->execute();
    //die(print_r($result));
    return $result;
}

我无法使用COUNT(b.id) AS count,因为它会报错,并且我不知道在addOrderby(???, 'DESC')中应该使用什么值?

4个回答

49

在v2.3.0或更早的版本中,要实现order by表达式需要很多错误和解决方法:

  1. The order by clause does not support expressions, but you can add a field with the expression to the select and order by it. So it's worth repeating that Tjorriemorrie's own solution actually works:

    $qb->select('b.year, COUNT(b.id) AS mycount')
       ->from('\My\Entity\Album', 'b')
       ->where('b.year IS NOT NULL')
       ->orderBy('mycount', 'DESC')
       ->groupBy('b.year');
    
  2. Doctrine chokes on equality (e.g. =, LIKE, IS NULL) in the select expression. For those cases the only solution I have found is to use a subselect or self-join:

    $qb->select('b, (SELECT count(t.id) FROM \My\Entity\Album AS t '.
                    'WHERE t.id=b.id AND b.title LIKE :search) AS isTitleMatch')
       ->from('\My\Entity\Album', 'b')
       ->where('b.title LIKE :search')
       ->andWhere('b.description LIKE :search')
       ->orderBy('isTitleMatch', 'DESC');
    
  3. To suppress the additional field from the result, you can declare it AS HIDDEN. This way you can use it in the order by without having it in the result.

    $qb->select('b.year, COUNT(b.id) AS HIDDEN mycount')
       ->from('\My\Entity\Album', 'b')
       ->where('b.year IS NOT NULL')
       ->orderBy('mycount', 'DESC')
       ->groupBy('b.year');
    

1
+1 for HIDDEN。这个技巧非常棒。Doctrine在返回结果中一直搞乱我的对象映射。 - Sergiu Dan Petru Barbus
1
像其他人说的那样,今天AS HIDDEN对我非常有帮助。 - Peter Bailey
很遗憾,在IN子查询中使用HIDDEN将无法正常工作。请参考我的示例:https://gist.github.com/webdevilopers/aa6a0ea06d7b5d4f0b04 - webDEVILopers

9

当使用COUNT(b.id) AS count时,您遇到了什么错误?可能是因为count是一个保留字。请尝试COUNT(b.id) AS idCount或类似的内容。

或者,尝试$qb->addOrderby('COUNT(b.id)', 'DESC');

您使用的数据库系统是什么(mysql、postgresql等)?


我认为DBAL不关心数据库是什么?无论如何,我已经用以下代码使其工作:$qb->select('b.year, COUNT(b.id) AS mycount')->from('\My\Entity\Album', 'b')->where('b.year IS NOT NULL')->orderBy('mycount', 'DESC')->groupBy('b.year'); 感谢指出关键字问题。 - Tjorriemorrie
1
你的替代方法不起作用。此外,如果你想将结果作为子查询重复使用 - (例如orderBy),在选择中添加COUNT是不起作用的。 - wdev

3
如果您希望您的Repository方法返回一个实体,您不能使用->select(),但是您可以使用一个隐藏的选择器->addSelect()
例如: $qb = $this->createQueryBuilder('q') ->addSelect('COUNT(q.id) AS HIDDEN counter') ->orderBy('counter'); $result = $qb->getQuery()->getResult(); $result将会是一个实体类对象。

HIDDEN语句非常有用,可以请求单个类的实体。 :+1: - prokki
此外,如果您正在从相关实体进行计数,则必须执行joingroup by操作:$qb = $this->createQueryBuilder('item')->join('item.features', 'feature')->addSelect('COUNT(feature.id) AS HIDDEN counter')->orderBy('counter', 'DESC'); - Bartłomiej Jakub Kwiatek

-2
请尝试使用此代码来处理 ci 2 + doctrine 2。
$where = " ";

$order_by = " ";
$row = $this->doctrine->em->createQuery("select a from company_group\models\Post a " 
            .$where." ".$order_by."")
            ->setMaxResults($data['limit'])
            ->setFirstResult($data['offset'])
            ->getResult();`

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