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

如何在Laravel中用查询构造器实现指定去重SQL查询?

问题解决:Laravel 实现指定SQL查询及重复数据问题处理

1. 修正查询构造器的拼写错误

你写的查询构造器里有个明显的拼写错误:orderBy('aerucul') 应该是 orderBy('articul'),修正后的标准构造器写法如下:

$products = Product::select('id', 'name', 'articul')
    ->where('category_id', 40)
    ->distinct()
    ->orderBy('articul')
    ->get();

2. 对应的模型方法实现

可以在 Product 模型中封装一个静态方法,方便复用这个查询逻辑:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    // 若模型名与表名一致,可省略$table定义
    protected $table = 'products';

    public static function getDistinctProductsByCategory($categoryId)
    {
        return self::select('id', 'name', 'articul')
            ->where('category_id', $categoryId)
            ->distinct()
            ->orderBy('articul')
            ->get();
    }
}

调用示例:

$products = Product::getDistinctProductsByCategory(40);

3. 重复数据问题的核心原因

你提到用 DB::select 直接执行原始SQL也出现重复,说明问题不是Laravel语法错误,而是对 DISTINCT 的逻辑理解偏差:

  • SELECT DISTINCT id, name, articul 是基于三个字段的组合去重,只要其中任意一个字段值不同,就会被视为独立记录保留。
  • 由于 id 是表的主键(默认自增唯一),即使name和articul完全相同,只要id不同,DISTINCT就不会合并这些记录。

如果你的真实需求是按articul字段去重(忽略id差异),应该改用groupBy,而非DISTINCT,具体写法分两种情况:

方式一:兼容严格SQL模式(推荐)

用ANY_VALUE函数包裹非分组字段,避免ONLY_FULL_GROUP_BY报错:

$products = Product::select(
    'articul',
    \DB::raw('ANY_VALUE(id) as id'),
    \DB::raw('ANY_VALUE(name) as name')
)
->where('category_id', 40)
->groupBy('articul')
->orderBy('articul')
->get();

方式二:关闭MySQL严格模式

修改config/database.php中mysql配置项的strict为false后,可直接写:

$products = Product::select('id', 'name', 'articul')
    ->where('category_id', 40)
    ->groupBy('articul')
    ->orderBy('articul')
    ->get();

4. 验证原始SQL的实际效果

你可以在phpMyAdmin中重新执行原始SQL,仔细查看结果中的id字段,会发现即使name和articul相同,id不同的记录依然会被保留——之前误以为原始SQL无重复,其实是忽略了id的唯一性导致的"假重复"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:04:59