Laravel集合基于自定义函数排序问题求助
问题描述
我有如下结构的items表:
CREATE TABLE IF NOT EXISTS `items` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `code` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, `unitPrice` decimal(8,2) NOT NULL, `quantity` int(11) NOT NULL, `totalSold` int(11) DEFAULT NULL, `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
原本用DB::table('items')->get();获取集合,现在想要得到和执行以下SQL相同的结果:
select `code`,(`unitPrice`*(`quantity`+`totalSold`)) as totalEarnIfsold from `items` order by `totalEarnIfsold` desc
尝试了以下写法但未成功:
$items_all->sortBy([ $totalEarnIfsold= fn ($a) => $a->unitPrice *($a->quantity+$a->totalSold), ['totalEarnIfsold', 'desc'], ]);
方案一:直接用Query Builder实现(推荐)
不要先全量获取集合再处理,直接在数据库层面完成计算和排序,效率更高,写法如下:
$result = DB::table('items') ->select( 'code', DB::raw('(unitPrice * (quantity + totalSold)) as totalEarnIfsold') ) ->orderBy('totalEarnIfsold', 'desc') ->get();
该写法和目标SQL执行结果完全一致,且数据库层面处理计算、排序的性能远优于PHP集合处理,尤其适合数据量较大的场景。
方案二:已获取集合后的修正写法
如果已经通过$items_all = DB::table('items')->get();拿到集合,需要分两步处理:
- 给集合元素添加
totalEarnIfsold计算字段 - 基于该字段降序排序
代码示例:
// 先添加计算字段 $items_all = $items_all->map(function ($item) { $item->totalEarnIfsold = $item->unitPrice * ($item->quantity + $item->totalSold); return $item; }); // 降序排序(sortByDesc直接实现降序,无需额外参数) $sortedItems = $items_all->sortByDesc('totalEarnIfsold'); // 若仅需code和totalEarnIfsold字段,可进一步筛选 $finalResult = $sortedItems->map(function ($item) { return collect($item)->only(['code', 'totalEarnIfsold']); });
你之前的写法错误在于:sortBy参数格式不符合要求,且未先给集合元素添加totalEarnIfsold字段,直接用不存在的字段排序必然无效。
内容的提问来源于stack exchange,提问作者Chargui Taieb
相关产品推荐
相关产品推荐

