Я хотел бы получить значение по следующему SQL, используя Eloquent ORM.
- SQL
SELECT COUNT(*) FROM
(SELECT * FROM abc GROUP BY col1) AS a;
Тогда я рассмотрел следующее.
- Код
$sql = Abc::from('abc AS a')->groupBy('col1')->toSql();
$num = Abc::from(\DB::raw($sql))->count();
print $num;
Я ищу лучшее решение.
Скажите, пожалуйста, простейшее решение.
В дополнение к ответу @delmadord и вашим комментариям:
В настоящее время нет способа создания подзапроса в FROM
, поэтому вам нужно вручную использовать команду raw, а затем, если необходимо, вы слейте все привязки:
$sub = Abc::where(..)->groupBy(..); // Eloquent Builder instance
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery()) // you need to get underlying Query Builder
->count();
Помните, что вам нужно объединить привязки в правильном порядке. Если у вас есть другие связанные предложения, вы должны поместить их после mergeBindings
:
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
// ->where(..) wrong
->mergeBindings($sub->getQuery()) // you need to get underlying Query Builder
// ->where(..) correct
->count();
Решение @JarekTkaczyk это именно то, что я искал. Единственное, что я пропустил, это то, как это сделать, когда вы используете
DB::table()
запросов. В этом случае я так делаю:
$other = DB::table( DB::raw("({$sub->toSql()}) as sub") )->select(
'something',
DB::raw('sum( qty ) as qty'),
'foo',
'bar'
);
$other->mergeBindings( $sub );
$other->groupBy('something');
$other->groupBy('foo');
$other->groupBy('bar');
print $other->toSql();
$other->get();
Особое внимание, как сделать mergeBindings
без использования метода getQuery()
Мне нравится делать что-то вроде этого:
Message::select('*')
->from(DB::raw("( SELECT * FROM `messages`
WHERE `to_id` = ".Auth::id()." AND `isseen` = 0
GROUP BY `from_id` asc) as `sub`"))
->count();
Это не очень элегантно, но просто.
Я не мог заставить ваш код делать желаемый запрос, AS является псевдонимом только для таблицы abc
, а не для производной таблицы.
Laravel Query Builder не подразумевает поддержку производных псевдонимов таблиц, DB:: raw, скорее всего, понадобится для этого.
Самое прямое решение, которое я мог придумать, почти идентично вашему, но производит запрос, как вы просили:
$sql = Abc::groupBy('col1')->toSql();
$count = DB::table(DB::raw("($sql) AS a"))->count();
Произведенный запрос
select count(*) as aggregate from (select * from `abc` group by `col1`) AS a;
Вам нужен суб-запрос? Вы можете попробовать что-то вроде
$num = Abc::groupBy('col1')->get()->count();
Не идеально, если у вас есть миллионы строк.
Argument 1 passed to Illuminate\Database\Query\Builder::mergeBindings() must be an instance of Illuminate\Database\Query\Builder, instance of Illuminate\Database\Eloquent\Builder given
, что я пропустил ?