为什么Laravel使用子查询来执行Eloquent has
和whereHas
方法而不是使用连接?例如,我构建了一个像这样的Eloquent查询:
Order::whereHas('orderProducts', function($query)
{
$query->where('product_id', $this->id);
})
->whereHas('status', function($query)
{
$query->where('sales_data', 1);
})
->where('ext_created_at', '>=', $startDate)
->where('ext_created_at', '<=', $endDate.' 23:59:59')
->distinct()
->count('id');
生成的查询是:
select count(distinct `id`) as aggregate from `orders` where `orders`.`deleted_at` is null and (select count(*) from `order_products` where `order_products`.`order_id` = `orders`.`id` and `product_id` = ? and `order_products`.`deleted_at` is null) >= 1 and (select count(*) from `order_statuses` where `orders`.`order_status_id` = `order_statuses`.`id` and `sales_data` = ? and `order_statuses`.`deleted_at` is null) >= 1 and `ext_created_at` >= ? and `ext_created_at` <= ?
此查询返回16
的结果。根据{{1}},这需要执行DB::getQueryLog()
。
然后我构建了另一个这样的查询:
23222.14 ms
生成的查询是:
DB::table('orders')
->leftJoin('order_products', 'orders.id', '=', 'order_products.order_id')
->leftJoin('order_statuses', 'orders.order_status_id', '=', 'order_statuses.id')
->whereNull('orders.deleted_at')
->where('order_products.product_id', $this->id)
->where('orders.ext_created_at', '>=', $startDate)
->where('orders.ext_created_at', '<=', $endDate.' 23:59:59')
->whereNull('order_products.deleted_at')
->where('order_statuses.sales_data', 1)
->distinct()
->count('orders.id')
此查询还会返回select count(distinct `orders`.`id`) as aggregate from `orders` left join `order_products` on `orders`.`id` = `order_products`.`order_id` left join `order_statuses` on `orders`.`order_status_id` = `order_statuses`.`id` where `orders`.`deleted_at` is null and `order_products`.`product_id` = ? and `orders`.`ext_created_at` >= ? and `orders`.`ext_created_at` <= ? and `order_products`.`deleted_at` is null and `order_statuses`.`sales_data` = ?
,但需要16
才能运行。显然,使用连接在这里有更好的性能,但是这只是特定于我的用例,还是加入通常更好的性能?如果是这样,为什么Eloquent不会在子查询中使用连接?我更愿意使用模型并使用所有优秀的Eloquent方法,如3.52 ms
和has
,但性能是如此显着不同,我被迫使用查询生成器自己构建查询
我在这里错过了什么吗?
我正在使用whereHas
。