Php Laravel:如何在Laravel查询生成器中使用派生表/子查询

Php Laravel:如何在Laravel查询生成器中使用派生表/子查询,php,laravel,subquery,query-builder,Php,Laravel,Subquery,Query Builder,编辑: 虽然这个问题最初是针对我下面描述的查询的,但我得到的答案几乎适用于所有与在Laravel中使用派生表/子查询相关的问题 原始问题: 最近我对laravel查询生成器有点着迷。它有一些非常好的特性,但我觉得它不是为更复杂的数据库操作而构建的 这是我试图构建的查询: select 'IFNULL(counted.product_count, 0) AS product_count', 'uncounted.value', 'uncounted.attribute_id', 'unc

编辑:

虽然这个问题最初是针对我下面描述的查询的,但我得到的答案几乎适用于所有与在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的产品目录。根据用户提供的过滤器/属性缩小产品范围。为了更好的用户体验,我想显示每个过滤器剩余的产品数量,这就是上面的查询所做的:计算某个属性的所有产品,其中产品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()语句。这不会让人觉得“拉拉维利什”或“雄辩”。你的第一次尝试看起来很接近。试试这个:

我删除了长名称空间引用,并建议您添加
use
语句,以使代码更具可读性


对于ifnull select,您肯定必须至少使用一条DB::raw()语句。至于剩下的,我建议把你已经尝试过的东西贴出来。请不要期望我们为你做所有的工作。亲爱的乔尔,我绝对不会让你为我做所有的工作!在过去的一周里,我尝试了很多事情,但是我似乎找不到正确的方法来翻译这个SQL以使用查询生成器。我知道IFNULL需要一个selectRaw()语句。我会把我尝试过的东西贴出来。更好的是,投上一票。:)很抱歉,我不能帮助你解决这个问题,但我希望其他人能。你可以考虑一个数据库视图,你可以创建一个迁移来创建视图。好吧,哇!这就成功了,非常感谢!有可能在多个嵌套选择/子查询中执行此技巧吗?我是否只需要在使用get()之前合并绑定?我注意到您已经发布了一条消息,这也解决了吗?如果是的话,我建议你删除老问题。这是真的。这比你的回答适用于他们两人的这个问题更普遍。我将对这个问题进行编辑,使其更一般地介绍如何在laravel/eloquent中使用派生表,以便其他人也可以在这里找到答案。我将删除我的另一个问题
mergeBindings
需要一个
Database\Query\Builder
的实例,而不是
Database\elogent\Query\Builder
,因此我无法将其用于模型上的
$subQuery
。在重构成普通的构建器之后,这非常有效
$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();