You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Doctrine QueryBuilder获取每个ArticleID的最早库存实体?

解决方案:通过子查询匹配每个ArticleID的最早记录

当然可以实现!你遇到的问题是直接用groupBy时,Doctrine并不会自动帮你取每组中date最早的那条记录——它只是按分组字段做聚合,返回的是每组的任意一条结果,所以orderBy无法影响分组后的最终取值。

正确的思路是先通过子查询获取每个符合条件的ArticleID对应的最早日期,再将主表与这个子查询关联,筛选出匹配的完整实体记录。下面是具体的Doctrine QueryBuilder实现:

// 第一步:构建子查询,获取每个目标ArticleID的最小日期
$subQuery = $this->getModelManager()->createQueryBuilder()
    ->select('sub.articleId, MIN(sub.date) as minDate')
    ->from(InventoryItem::class, 'sub')
    ->where('sub.articleId IN (:articleIds)')
    ->andWhere('sub.quantity > 0')
    ->groupBy('sub.articleId')
    ->getDQL();

// 第二步:主查询关联子查询,筛选出匹配的完整记录
$rows = $this->getModelManager()->createQueryBuilder()
    ->select('ii')
    ->from(InventoryItem::class, 'ii')
    ->join(
        sprintf('(%s)', $subQuery), // 将子查询作为临时表关联
        'subQ',
        'WITH',
        'ii.articleId = subQ.articleId AND ii.date = subQ.minDate'
    )
    ->where('ii.articleId IN (:articleIds)')
    ->andWhere('ii.quantity > 0')
    ->setParameter('articleIds', $articleIds)
    ->getQuery()
    ->getResult();

代码逻辑说明:

  • 子查询部分:针对articleId在指定列表、quantity>0的记录,按articleId分组,计算每组的最小date,得到每个ArticleID对应的最早日期映射。
  • 主查询部分:将主表与子查询结果做关联,只保留articleId和date同时匹配子查询结果的记录,这样就确保了每个ArticleID仅返回date最早的那条实体。

用你的测试数据验证,这个查询会返回:

ID | ArticleID | Quantity | Date
2  | 200       | 20       | 2018-07-31
3  | 100       | 40       | 2018-05-31

完全符合你的期望。如果需要对最终结果做排序,直接在主查询末尾添加->orderBy('ii.articleId', 'ASC')(或其他排序规则)即可,不会影响分组筛选的逻辑。

内容的提问来源于stack exchange,提问作者Torben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:39:47