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

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();拿到集合,需要分两步处理:

  1. 给集合元素添加totalEarnIfsold计算字段
  2. 基于该字段降序排序

代码示例:

// 先添加计算字段
$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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:01:07