Laravel中如何计算已交付订单的平均配送时间?
解决Laravel中计算已交付订单平均配送时间的问题
嘿,我明白你现在卡在哪了——你之前的代码逻辑完全走偏了,直接对updated_at字段求平均得到的是日期本身的平均值,不是配送时长的平均值,这就是为啥会出现那串奇怪的数字,还导致Carbon解析失败的原因。
错误原因拆解
Order::where('status', '=', '8')->avg('updated_at') 干的事儿是把所有已交付订单的updated_at日期转成数据库底层的数值(比如MySQL会把datetime转成20240520123045这类数字),然后求这些数字的平均值,得到的结果根本不是有效的时间戳/日期,自然没法用Carbon解析成天数。
我们真正要算的是每个订单的配送时长(交付时间 - 订单起始时间)的平均值,而不是日期的平均值。
正确解决方案
根据你的订单数据量,推荐两种实用方法:
方法1:数据库层面计算(高效,适合大量订单)
直接在数据库里计算每个订单的配送时长差值,再求平均值,性能拉满:
假设你的订单有created_at字段(订单创建时间,作为配送的起始时间),不同数据库的函数略有区别:
MySQL版本
$avgDeliveryDays = Order::where('status', 8) ->selectRaw('AVG(DATEDIFF(updated_at, created_at)) as avg_days') ->value('avg_days');
DATEDIFF函数会直接返回updated_at和created_at之间的天数差,再通过AVG求平均值。
PostgreSQL版本
$avgDeliveryDays = Order::where('status', 8) ->selectRaw('AVG(EXTRACT(DAY FROM (updated_at - created_at))) as avg_days') ->value('avg_days');
SQLite版本
$avgDeliveryDays = Order::where('status', 8) ->selectRaw('AVG(JULIANDAY(updated_at) - JULIANDAY(created_at)) as avg_days') ->value('avg_days');
如果你的配送起始时间不是created_at(比如是发货时间shipped_at),把字段替换成对应的就行。
方法2:PHP层面计算(灵活,适合少量订单)
如果需要更灵活的时间精度控制(比如精确到小时/分钟),可以先拉取订单数据,再在PHP里计算:
$orders = Order::where('status', 8)->select('updated_at', 'created_at')->get(); $totalDuration = 0; $orderCount = $orders->count(); if ($orderCount === 0) { $avgDeliveryDays = 0; } else { foreach ($orders as $order) { // 计算两个日期的天数差,需要精确到小时就换成diffInHours $diff = Carbon::parse($order->updated_at)->diffInDays(Carbon::parse($order->created_at)); $totalDuration += $diff; } $avgDeliveryDays = $totalDuration / $orderCount; }
最后验证
不管用哪种方法,得到的$avgDeliveryDays就是你要的平均配送天数,直接用就行,不用再折腾Carbon解析啦。
内容的提问来源于stack exchange,提问作者Jadasdas
相关产品推荐
相关产品推荐

