Laravel 4.2中如何不查询全量数据统计分组结果数量?
解决Laravel 4.2中Eloquent分组后高效统计分组数量的问题
嘿,这个问题我在维护Laravel 4.x旧项目时也遇到过!确实,直接调用groupBy()->count()会返回分组前的总行数,这是因为Laravel 4.2的Query Builder在执行count()时会重置查询的select部分,直接执行count(*),完全忽略了之前的groupBy条件。
要高效获取分组后的组合数量,不用拉取全量分组数据,这里有两种可靠的方案:
方案1:子查询统计分组数
让数据库先完成分组操作,再统计分组结果的行数,这是最准确且高效的方式,不会返回多余数据:
// 使用Eloquent模型的写法 $groupCount = CustomerTable::from( DB::raw('(SELECT 1 FROM customer_table GROUP BY country, city) AS grouped') )->count(); // 或者用DB门面直接写(效果一致) $groupCount = DB::table( DB::raw('(SELECT 1 FROM customer_table GROUP BY country, city) AS grouped') )->count();
这个查询会先创建一个临时表grouped,里面只包含分组后的空占位符(1),然后统计这个临时表的行数,就是你要的分组组合数。
方案2:利用DISTINCT统计唯一组合
如果你的country和city组合不会出现拼接冲突(比如不会有country=US+city=ANewYork和country=USA+city=NewYork这种拼接后相同的情况),也可以用distinct配合拼接字段来统计:
$groupCount = CustomerTable::distinct()->count(DB::raw('CONCAT(country, city)'));
这种写法更简洁,但要注意拼接字段的唯一性风险,优先推荐方案1。
为什么原来的写法无效?
再补充下原因:Laravel 4.2的count()方法内部会调用->select(DB::raw('count(*) as aggregate')),这会覆盖你之前的groupBy逻辑,最终执行的SQL是select count(*) as aggregate from customer_table,自然返回的是总行数。
内容的提问来源于stack exchange,提问作者cytsunny
相关产品推荐
相关产品推荐

