Symfony框架下如何用Query Builder获取最后10条Invoice并按amount排序
问题
我用Symfony开发,有个Invoice表,字段是id、createdAt、amount。想通过Query Builder实现:先拿最后创建的10条记录,再把这10条按amount排序。
之前试了这段代码:
$invoices->orderBy('i.createdAt', 'DESC') ->addOrderBy('i.amount', 'ASC') ->setMaxResults(10);
结果不对,它只是按createdAt排序取前10,根本没按我要的逻辑对这10条再排序。后来我自己凑了个变通方案:
$subquery = $this->createQueryBuilder('invoice') ->orderBy('invoice.createdAt', 'DESC') ->setMaxResults(10) ->getQuery() ->getResult(); $idArray = []; foreach ($subquery as $item) { $idArray[] = $item->getId(); } $invoices->where('i.id IN (:items)') ->setParameter('items', $idArray);
但感觉有点啰嗦,有没有更简洁的写法?
解决方案
当然可以用Query Builder直接实现,而且有更简洁的方式:
方式一:子查询+IN表达式(推荐)
直接用子查询获取最新10条的ID,主查询筛选后按金额排序,全程用Query Builder完成,不用手动处理数组:
// 子查询:获取最新10条Invoice的ID $subQuery = $this->createQueryBuilder('sub') ->select('sub.id') ->orderBy('sub.createdAt', 'DESC') ->setMaxResults(10); // 主查询:筛选ID在子查询结果中,再按amount排序 $invoices = $this->createQueryBuilder('i') ->where($this->createQueryBuilder()->expr()->in('i.id', $subQuery->getDQL())) ->orderBy('i.amount', 'ASC') ->getQuery() ->getResult();
方式二:优化你的变通方案
如果还是想用先取ID的方式,可以直接用getScalarResult()拿到ID数组,不用循环提取:
// 直接获取ID数组 $idArray = $this->createQueryBuilder('invoice') ->select('invoice.id') ->orderBy('invoice.createdAt', 'DESC') ->setMaxResults(10) ->getQuery() ->getScalarResult(); // 转成一维数组 $idArray = array_column($idArray, 'id'); // 主查询筛选并排序 $invoices = $this->createQueryBuilder('i') ->where('i.id IN (:items)') ->setParameter('items', $idArray) ->orderBy('i.amount', 'ASC') ->getQuery() ->getResult();
为什么你原来的代码不行?
你原来的写法是全局先按createdAt降序,再按amount升序排序,然后取前10条。这意味着数据库会先把所有记录按createdAt排,遇到createdAt相同的才会按amount排,最后取前10——这和你要的「先挑出最新10条,再单独给这10条按amount排序」逻辑完全不是一回事。
内容的提问来源于stack exchange,提问作者AIexplains
相关产品推荐
相关产品推荐

