Laravel:如何在 laravel 查询构建器中使用派生表/子查询
Laravel: how to use derived tables / subqueries in the laravel query builder
编辑:
虽然这个问题最初是针对我在下面描述的查询的,但我得到的答案适用于几乎所有与在 Laravel
中使用派生表/子查询相关的问题
原题:
最近我有点卡在 laravel 查询生成器上。它有一些非常好的特性,但我觉得它不是为更复杂的数据库操作而构建的。
这是我要构建的查询:
select
'IFNULL(counted.product_count, 0) AS product_count',
'uncounted.value',
'uncounted.attribute_id',
'uncounted.attribute_option_id'
from (
select
'counted.id',
'counted.attribute_id',
'counted.value',
'count(counted.attribute_id) AS product_count'
from `attribute_options` as `counted`
where `counted.product_id` in (?, ?, ?, ?, ?)
group by `counted.attribute_option_id`
) as 'counted'
right join 'attribute_options' as 'uncounted'
on 'counted.id' = 'uncounted.id'
group by 'attribute_option_id'
查询说明:
我正在 laravel 中为我的产品目录构建分面搜索。根据 filters/attributes 用户提供的产品缩小范围。为了更好的用户体验,我想显示每个过滤器剩余的产品数量,这就是上面的查询所做的:计算某个属性的所有产品,其中 product_id 在产品 ID 数组中。
我的尝试:
$productIds = [ 1, 2, 3, 4, 5 ];
$subQuery = \DB::table('attribute_options')->selectRaw('counted.id, counted.attribute_id, counted.value, count(counted.attribute_id) AS product_count')
->from('attribute_options AS counted')
->whereIn('counted.product_id', $productIds)
->groupBy('counted.attribute_option_id')
->mergeBindings($subQuery);
$query = Model::selectRaw('IFNULL(counted.product_count, 0) AS product_count, uncounted.value, uncounted.attribute_id, uncounted.attribute_option_id')
->from(\DB::raw(' ( ' . $subQuery->toSql() . ' ) AS counted '))
->rightJoin('attribute_options AS uncounted', 'counted.id', '=', 'uncounted.id')
->groupBy('attribute_option_id')
->get();
请帮助我,因为我不喜欢使用 DB::raw() 或 DB::select() 语句。那不会感觉 "Laravelish" 或 "Eloquent".
你的第一次尝试看起来很接近。试试这个:
我删除了长名称空间引用并建议您添加一个 use
语句以使您的代码更具可读性
$productIds = [ 1, 2, 3, 4, 5 ];
$subQuery = DB::table('attribute_options AS counted')->selectRaw('counted.id, counted.attribute_id, counted.value, count(counted.attribute_id) AS product_count')
->whereIn('counted.product_id', $productIds)
->groupBy('counted.attribute_option_id')
$query = AttributeOption::selectRaw('IFNULL(counted.product_count, 0) AS product_count, uncounted.value, uncounted.attribute_id, uncounted.attribute_option_id')
->from(\DB::raw(' ( ' . $subQuery->toSql() . ' ) AS counted '))
->mergeBindings($subQuery->getQuery())
->rightJoin('attribute_options AS uncounted', 'counted.id', '=', 'uncounted.id')
->groupBy('attribute_option_id')
->get();
编辑:
虽然这个问题最初是针对我在下面描述的查询的,但我得到的答案适用于几乎所有与在 Laravel
中使用派生表/子查询相关的问题原题:
最近我有点卡在 laravel 查询生成器上。它有一些非常好的特性,但我觉得它不是为更复杂的数据库操作而构建的。
这是我要构建的查询:
select
'IFNULL(counted.product_count, 0) AS product_count',
'uncounted.value',
'uncounted.attribute_id',
'uncounted.attribute_option_id'
from (
select
'counted.id',
'counted.attribute_id',
'counted.value',
'count(counted.attribute_id) AS product_count'
from `attribute_options` as `counted`
where `counted.product_id` in (?, ?, ?, ?, ?)
group by `counted.attribute_option_id`
) as 'counted'
right join 'attribute_options' as 'uncounted'
on 'counted.id' = 'uncounted.id'
group by 'attribute_option_id'
查询说明: 我正在 laravel 中为我的产品目录构建分面搜索。根据 filters/attributes 用户提供的产品缩小范围。为了更好的用户体验,我想显示每个过滤器剩余的产品数量,这就是上面的查询所做的:计算某个属性的所有产品,其中 product_id 在产品 ID 数组中。
我的尝试:
$productIds = [ 1, 2, 3, 4, 5 ];
$subQuery = \DB::table('attribute_options')->selectRaw('counted.id, counted.attribute_id, counted.value, count(counted.attribute_id) AS product_count')
->from('attribute_options AS counted')
->whereIn('counted.product_id', $productIds)
->groupBy('counted.attribute_option_id')
->mergeBindings($subQuery);
$query = Model::selectRaw('IFNULL(counted.product_count, 0) AS product_count, uncounted.value, uncounted.attribute_id, uncounted.attribute_option_id')
->from(\DB::raw(' ( ' . $subQuery->toSql() . ' ) AS counted '))
->rightJoin('attribute_options AS uncounted', 'counted.id', '=', 'uncounted.id')
->groupBy('attribute_option_id')
->get();
请帮助我,因为我不喜欢使用 DB::raw() 或 DB::select() 语句。那不会感觉 "Laravelish" 或 "Eloquent".
你的第一次尝试看起来很接近。试试这个:
我删除了长名称空间引用并建议您添加一个 use
语句以使您的代码更具可读性
$productIds = [ 1, 2, 3, 4, 5 ];
$subQuery = DB::table('attribute_options AS counted')->selectRaw('counted.id, counted.attribute_id, counted.value, count(counted.attribute_id) AS product_count')
->whereIn('counted.product_id', $productIds)
->groupBy('counted.attribute_option_id')
$query = AttributeOption::selectRaw('IFNULL(counted.product_count, 0) AS product_count, uncounted.value, uncounted.attribute_id, uncounted.attribute_option_id')
->from(\DB::raw(' ( ' . $subQuery->toSql() . ' ) AS counted '))
->mergeBindings($subQuery->getQuery())
->rightJoin('attribute_options AS uncounted', 'counted.id', '=', 'uncounted.id')
->groupBy('attribute_option_id')
->get();