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. Продукты сужаются на основе фильтров / атрибутов, которые пользователи предоставляют. Для лучшего удобства работы я хочу показать количество продуктов, оставшихся для каждого фильтра, это то, что делает вышеописанный запрос: подсчет всех продуктов для определенного атрибута. WHERE product_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».

Solutions Collecting From Web of "Laravel: как использовать производные таблицы / подзапросы в построителе запросов laravel"

Ваша первая попытка выглядит довольно близко. Попробуй это:

Я удалил длинную ссылку на пространство имен и предложил добавить инструкцию 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) ->rightJoin('attribute_options AS uncounted', 'counted.id', '=', 'uncounted.id') ->groupBy('attribute_option_id') ->get();