Laravel中all与select方法报错:如何合并查询避免多次请求?
解决Laravel中一次查询获取总订单数与指定状态订单平均更新时间的问题
首先得搞清楚你第一次代码报错的原因:当调用Order::all()时,Laravel已经执行了查询并把结果返回成Eloquent Collection(集合),而select是QueryBuilder(查询构建器)的专属方法,集合类根本没有这个方法,所以才会抛出Method select does not exist的错误。
想要只执行一次查询就拿到你需要的两个数据(总订单数、status=8的订单平均更新时间),可以直接用原生SQL聚合函数结合CASE WHEN,通过一次查询同时计算两个值,具体代码如下:
// 一次查询获取总订单数和指定状态的平均更新时间 $stats = DB::table('orders') ->select( DB::raw('COUNT(*) as all_orders'), // 计算总订单数 DB::raw('AVG(CASE WHEN status = 8 THEN updated_at END) as order_average') // 仅计算status=8的订单的updated_at平均值 ) ->first(); // 提取需要的数据 $allorders = $stats->all_orders; $deliveryQuery = $stats->order_average;
代码说明:
COUNT(*)会统计所有订单的数量,完全对应你原来的$orders->count()逻辑;CASE WHEN status = 8 THEN updated_at END会只筛选出status为8的订单的updated_at值,其他订单的该字段会被置为NULL,而AVG()函数会自动忽略NULL值,最终得到的就是符合条件的订单的平均更新时间;- 整个查询只会执行一次,避免了两次查询带来的性能损耗。
如果你更倾向于使用Eloquent模型而不是直接操作DB门面,也可以这样写:
$stats = Order::select( DB::raw('COUNT(*) as all_orders'), DB::raw('AVG(CASE WHEN status = 8 THEN updated_at END) as order_average') ) ->first();
效果和上面的代码完全一致,只是用Order模型来启动查询。
内容的提问来源于stack exchange,提问作者Jadasdas
相关产品推荐
相关产品推荐

