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

Laravel Eloquent同查询中如何让HAVING与WHERE实现OR逻辑?

问题解答

逻辑可行性

你需要的普通字段筛选 OR 聚合字段筛选的逻辑可以实现,但SQL原生不支持直接写WHERE ... OR HAVING ...的语法,两者执行时机不同:WHERE用于过滤聚合前的原始数据行,HAVING用于过滤聚合后的分组结果,需要通过调整查询结构实现,通用实现思路有两种:

  • 思路1:将非聚合字段的筛选条件全部挪到HAVING子句中,和聚合字段的筛选条件直接用OR连接。该方案实现简单性能高,适合GROUP BY的字段包含所有非聚合筛选字段的场景(你的示例中GROUP BY id,name、age都属于id对应的唯一属性,符合要求)。
  • 思路2:把带聚合的查询封装为子查询,外层查询统一用WHERE判断所有筛选条件,不需要区分聚合/非聚合字段,适用所有场景。

Laravel Eloquent 实现代码

思路1实现(HAVING合并所有条件,优先推荐)

$keyword = '%asdf%'; // 替换为你的实际筛选关键词
$list = YourModel::query() // 替换为你自己的模型类名
    ->select('id', 'name', 'age', \DB::raw('SUM(quantity) as sum_quantity'))
    ->groupBy('id', 'name', 'age') // MySQL严格模式下需要把所有非聚合查询字段放入GROUP BY
    // 所有筛选条件统一放入HAVING用OR连接
    ->having(function ($query) use ($keyword) {
        $query->where('name', 'like', $keyword)
            ->orWhere('age', 'like', $keyword)
            ->orWhere('sum_quantity', 'like', $keyword);
    })
    ->get();

该方案可以在聚合前保留必要的过滤条件提升性能,如果你有不需要OR的全局过滤条件,直接在GROUP BY前加正常WHERE语句即可。

思路2实现(子查询方案,全场景兼容)

如果你的场景不满足非聚合字段可放入HAVING的要求,可以用子查询封装聚合结果后统一筛选:

$keyword = '%asdf%';
// 先构造聚合子查询
$subQuery = YourModel::query()
    ->select('id', 'name', 'age', \DB::raw('SUM(quantity) as sum_quantity'))
    ->groupBy('id', 'name', 'age');

// 外层查询统一处理所有OR筛选条件,可直接返回模型实例
$list = YourModel::query()
    ->fromSub($subQuery, 't')
    ->where('name', 'like', $keyword)
    ->orWhere('age', 'like', $keyword)
    ->orWhere('sum_quantity', 'like', $keyword)
    ->get();

注意事项

  • 若使用MySQL严格模式,GROUP BY子句必须包含所有SELECT中出现的非聚合字段,否则会抛出语法错误。
  • 全列筛选扩展时,普通字段直接加OR条件即可,聚合字段在思路1中加HAVING条件、思路2中直接加普通WHERE条件即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 17:36:04