I'd like to get value by the following SQL using Eloquent ORM.
- SQL
SELECT COUNT(*) FROM
(SELECT * FROM abc GROUP BY col1) AS a;
Then I considered the following.
- Code
$sql = Abc::from('abc AS a')->groupBy('col1')->toSql();
$num = Abc::from(\DB::raw($sql))->count();
print $num;
I'm looking for a better solution.
Please tell me simplest solution.
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:Special atention how to make the
mergeBindings
without using thegetQuery()
methodFrom laravel 5.5 there is a dedicated method for subqueries and you can use it like this:
Abc::selectSub(function($q) { $q->select('*')->groupBy('col1'); }, 'a')->count('a.*');
or
Abc::selectSub(Abc::select('*')->groupBy('col1'), 'a')->count('a.*');
I could not made your code to do the desired query, the AS is an alias only for the table
abc
, not for the derived table. Laravel Query Builder does not implicitly support derived table aliases, DB::raw is most likely needed for this.The most straight solution I could came up with is almost identical to yours, however produces the query as you asked for:
The produced query is
Laravel v5.6.12 (2018-03-14) added
fromSub()
andfromRaw()
methods to query builder (#23476).The accepted answer is correct but can be simplified into:
The above snippet produces the following SQL:
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:Mind that you need to merge bindings in correct order. If you have other bound clauses, you must put them after
mergeBindings
:I like doing something like this:
It's not very elegant, but it's simple.