Laravel中分组查询Products模型时排除sizebarcode空值并保留空记录
我来帮你搞定这个Laravel查询需求!你要的效果是保留所有sizebarcode为空的记录,同时对非空的sizebarcode去重(分组),最终拿到所有空值记录+非空的唯一sizebarcode记录对吧?咱们可以用**联合查询(Union)**来实现,直接上思路和代码:
解决方案
我们可以把查询拆成两个独立部分,再合并结果:
1. 先获取所有sizebarcode为空的记录
这部分不需要分组,直接查询即可:
$nullSizeProducts = $category->products_front() ->whereNull('sizebarcode') ->select('id', 'description', 'barcode', 'sizebarcode', 'price');
2. 再获取sizebarcode非空的唯一值记录
这里要排除空值,同时确保每个非空的sizebarcode只返回一条记录。有两种实现方式:
方式一:用distinct(简单直接,适合仅去重场景)
$uniqueSizeProducts = $category->products_front() ->whereNotNull('sizebarcode') ->select('id', 'description', 'barcode', 'sizebarcode', 'price') ->distinct('sizebarcode');
方式二:用groupBy(适合需要聚合字段的场景)
如果你的MySQL开启了ONLY_FULL_GROUP_BY模式,直接用groupBy非聚合字段会报错,这时候可以配合聚合函数使用,比如取每组的最小ID、最低价格:
$uniqueSizeProducts = $category->products_front() ->whereNotNull('sizebarcode') ->selectRaw('MIN(id) as id, description, barcode, sizebarcode, MIN(price) as price') ->groupBy('sizebarcode', 'description', 'barcode');
3. 合并两部分结果并集成到控制器
把上面两个查询用union合并,最终拿到你需要的所有数据:
// 先找到对应的分类 $category = Category::where('slug', $slug)->firstOrFail(); // 第一部分:空sizebarcode的记录 $nullSizeProducts = $category->products_front() ->whereNull('sizebarcode') ->select('id', 'description', 'barcode', 'sizebarcode', 'price'); // 第二部分:非空且唯一的sizebarcode记录 $uniqueSizeProducts = $category->products_front() ->whereNotNull('sizebarcode') ->select('id', 'description', 'barcode', 'sizebarcode', 'price') ->distinct('sizebarcode'); // 合并查询并获取结果 $products = $nullSizeProducts->union($uniqueSizeProducts)->get();
额外提示
- 如果
products_front()是自定义的关联或查询作用域,确保它的逻辑不会和我们的条件冲突 - 要是需要对最终结果排序,可以在
get()前加上->orderBy('sizebarcode', 'asc')(空值默认会排在最前面,取决于数据库配置) - 如果你需要的是分组后的聚合数据(比如每个sizebarcode的最低/最高价格),可以调整
select里的字段为聚合函数,比如selectRaw('sizebarcode, MIN(price) as min_price')
内容的提问来源于stack exchange,提问作者Benfactor
相关产品推荐
相关产品推荐

