为了账号安全,请及时绑定邮箱和手机立即绑定

Laravel 基于关系值的排序模型

Laravel 基于关系值的排序模型

PHP
慕尼黑5688855 2023-11-03 10:49:14
我有一个名为“业务”的模型,一个企业可以提供多种服务。我有另一种模型,称为“付款”。付款记录了人们支付的服务费用。一项服务可以有多个付款。我打算根据收到的付款获取排名前 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'));
查看完整描述

1 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

我想您可以使用联接查询直接从数据库获取排名前 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(),如果您使用任何其他数据库,您可以使用备用函数。


查看完整回答
反对 回复 2023-11-03
  • 1 回答
  • 0 关注
  • 62 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信