Laravel 基于关系值的排序模型

我有一个名为“业务”的模型,一个企业可以提供多种服务。我有另一种模型,称为“付款”。付款记录了人们支付的服务费用。一项服务可以有多个付款。我打算根据收到的付款获取排名前 10 名和排名最差的 10 家企业。下面的代码工作正常,但效率很低。我必须循环遍历整个数据才能检索我需要的信息。有更有效的方法来实现这一目标吗?


$businesses = Business::with(['services'])->get();

foreach($businesses as $business){

    $id = $business->id;

    $name = $business->display_name;

    $services = $business->services;

    $businessRevenue = 0;

    if(count($services)>0){

        foreach($services as $service){

            $serviceId = $service->id;

            $totalAmount = PaymentTransaction::whereHas('invoice', function($query) use ($serviceId){

                $query->where('product_code_id', $serviceId);

            })->where('amount_paid', ">", 0)->sum('amount_paid');

            $businessRevenue= $businessRevenue + $totalAmount;

        }

    }

    $businessArray = (object) array('id'=> $id, 'name'=> $name, 'revenue'=> $businessRevenue);

    

    array_push($transformedBusiness, $businessArray);

}

$topBusiness = $bottomBusiness = $transformedBusiness;

usort($bottomBusiness, function($a, $b) {return strcmp($a->revenue, $b->revenue);});

usort($topBusiness, function($a, $b) {return strcmp($b->revenue, $a->revenue);});

$topBusiness = array_slice($topBusiness, 0, 10);

$bottomBusiness = array_slice($bottomBusiness, 0, 10);

return view('report.department_performance', compact('topBusiness', 'bottomBusiness'));


慕尼黑5688855
浏览 110回答 1
1回答

慕森卡

我想您可以使用联接查询直接从数据库获取排名前 10 的企业和排名最低的 10 家企业,而不是循环所有企业记录并手动计算其收入对于排名前 10 的业务,您可以对其余相关表使用内部联接$topBusinesses = DB::query()      ->select('b.id', 'b.display_name',  DB::raw('sum(p.amount_paid) as revenue')      ->from('business as b')      ->join('service as s', 'b.id', '=', 's.business_id')      ->join('invoice as i', 's.id', '=', 'i.product_code_id')      ->join('payment_transaction as p', function ($join) {                    $join->on('p.id', '=', 'i.payment_transaction')                     ->where('p.amount_paid', '>', 0);      })      ->groupBy('b.id', 'b.display_name')      ->orderByDesc('revenue')      ->limit(10)      ->get();对于最低 10 个业务,请使用发票和 payment_transaction 的左联接,这样,如果这些表中没有某个业务的记录,您仍然可以获得这些业务记录$lowestBusinesses = DB::query()      ->select('b.id', 'b.display_name',  DB::raw('coalesce(sum(p.amount_paid),0) as revenue')      ->from('business as b')      ->join('service as s', 'b.id', '=', 's.business_id')      ->leftJoin('invoice as i', 's.id', '=', 'i.product_code_id')      ->leftJoin('payment_transaction as p', function ($join) {                    $join->on('p.id', '=', 'i.payment_transaction')                     ->where('p.amount_paid', '>', 0);       })      ->groupBy('b.id', 'b.display_name')      ->orderBy('revenue')      ->limit(10)      ->get();我使用 MySQL合并函数在返回 null 的情况下显示 0 值sum(),如果您使用任何其他数据库,您可以使用备用函数。
打开App,查看更多内容
随时随地看视频慕课网APP