首页 文章

Laravel:如何在laravel查询构建器中使用派生表/子查询

提问于
浏览
11

Edit:

虽然这个问题最初是针对我在下面描述的查询所特有的,但我得到的答案几乎适用于与在Laravel中使用派生表/子查询相关的几乎所有问题 .

Original Question:

最近我有点卡在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'

Explanation of the query: 我'm building a faceted search for my product catalog in laravel. Products are narrowed down based on the filters/attributes users provide. For better user experience I want to show the amount of products left for each filter, that' s上面的查询的作用:计算某个属性的所有产品,其中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” .

1 回答

  • 20

    你的第一次尝试非常接近 . 试试这个:

    我删除了长命名空间引用,并建议您添加 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();
    

相关问题