web-dev-qa-db-ja.com

Laravel:laravelクエリビルダーで派生テーブル/サブクエリを使用する方法

編集:

この質問はもともと私が下で説明しているクエリに固有のものでしたが、私が得た答えは、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で製品カタログのファセット検索を作成しています。製品は、ユーザーが提供するフィルター/属性に基づいて絞り込まれます。ユーザーエクスペリエンスを向上させるために、各フィルターに残っている製品の量を表示したいと思います。これは、上記のクエリが行うことです。つまり、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」を感じないでしょう。

12
Luuk Van Dongen

あなたの最初の試みはかなり近いように見えます。これを試して:

長い名前空間参照を削除し、コードを読みやすくするために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();
20
lukasgeiter