Laravel中用distinct获取关联模型唯一颜色行的问题
Laravel关联查询中distinct不生效的原因及解决办法
假设有Category模型与Product模型为hasMany关联,Product模型包含color字段。想要返回所有分类及其对应分类下的所有唯一颜色,尝试了以下代码:
return Category::with(['products' => function ($query) { $query->distinct('color'); }])->get();
原本希望借此避免在PHP层面过滤(减少不必要的资源消耗),但这段代码并未生效,仍返回包含重复颜色的所有产品,原因如下:
- SQL标准中的
DISTINCT是针对整行记录去重,而非单个字段。Laravel的distinct()方法接收参数时,并不会生成DISTINCT(color)这种语法(多数主流数据库也不支持该写法),最终生成的SQL仍是SELECT DISTINCT * FROM products ...。只要产品的其他字段(如id、name等)存在差异,整行记录就会被判定为唯一,自然无法按颜色去重。
你提到在distinct()前添加select指定字段就会生效,原理是:
- 当添加
select('color')后,生成的SQL变为SELECT DISTINCT color FROM products ...,此时查询结果仅包含color字段,DISTINCT会基于该字段整列进行去重,重复的颜色记录会被过滤,因此能得到唯一颜色列表。这完全符合SQL中DISTINCT的工作逻辑——它会根据查询返回的所有字段组合判断重复,仅保留唯一组合。
如果要更高效地实现需求,也可以用分组查询替代:
return Category::with(['products' => function ($query) { $query->select('color', 'category_id') ->groupBy('color', 'category_id'); }])->get();
内容的提问来源于stack exchange,提问作者norr
相关产品推荐
相关产品推荐

