How to select from subquery using Laravel Query Builder?
In addition to @delmadord's answer and your comments:
Currently there is no method to create subquery in FROM
clause, so you need to manually use raw statement, then, if necessary, you will merge all the bindings:
$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();
Mind that you need to merge bindings in correct order. If you have other bound clauses, you must put them after 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();
Laravel v5.6.12 (2018-03-14) added fromSub()
and fromRaw()
methods to query builder (#23476).
The accepted answer is correct but can be simplified into:
DB::query()->fromSub(function ($query) { $query->from('abc')->groupBy('col1');}, 'a')->count();
The above snippet produces the following SQL:
select count(*) as aggregate from (select * from `abc` group by `col1`) as `a`
The solution of @JarekTkaczyk it is exactly what I was looking for. The only thing I miss is how to do it when you are using DB::table()
queries. In this case, this is how I do it:
$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();
Special atention how to make the mergeBindings
without using the getQuery()
method