withcount不支持按日统计,只能做模型级总数聚合;需用selectraw+groupby实现每日计数,多表对齐用子查询join,分表场景建议建视图统一查询。

withCount 本身不支持按「每日」维度统计,它只做模型级关联数量聚合(如“用户总订单数”),无法直接产出 2026-10-15: 3单, 2026-10-16: 7单 这类时间序列结果。要实现每日关联数据统计,必须切换到聚合查询模式,而不是依赖 withCount。
用 selectRaw + groupBy 实现每日计数
适用于「查某类模型每天产生多少条关联记录」,例如:每个商户每天新增多少笔成功订单。
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
$stats = DB::table('orders')
->selectRaw('DATE(created_at) as day, COUNT(*) as count')
->where('status', 'success')
->whereBetween('created_at', [
Carbon::now()->startOfDay()->subDays(30),
Carbon::now()->endOfDay()
])
->groupBy('day')
->orderBy('day')
->get();
返回结果形如:
[{"day": "2026-10-15", "count": 4}, {"day": "2026-10-16", "count": 12}]
多表联查下的每日对齐统计(如用户日行为 vs 全站均值)
当需对比「某用户每天学习时长」和「全站同日平均时长」,两个数据源不同、但日期必须严格对齐:
$userData = DB::table('user_logs')
->selectRaw('DATE(created_at) as log_date, SUM(duration) as user_total')
->where('user_id', auth()->id())
->groupBy('log_date');
$avgData = DB::table('user_logs')
->selectRaw('DATE(created_at) as avg_date, AVG(duration) as daily_avg')
->groupBy('avg_date');
$result = DB::table(DB::raw("({$userData->toSql()}) as user_data"))
->join(DB::raw("({$avgData->toSql()}) as avg_data"), 'user_data.log_date', '=', 'avg_data.avg_date')
->mergeBindings($userData->getBindings())
->mergeBindings($avgData->getBindings())
->select('user_data.log_date', 'user_data.user_total', 'avg_data.daily_avg')
->get();
注意:手动绑定参数防注入,避免拼接字符串。
分表场景下查近30天每日订单数
若订单已按月分表(orders_202609, orders_202610…),推荐建数据库视图 orders_all:
CREATE VIEW orders_all AS SELECT * FROM orders_202609 UNION ALL SELECT * FROM orders_202610 UNION ALL SELECT * FROM orders_202611;
然后在 Laravel 中新建模型或直接查:
$stats = DB::table('orders_all')
->selectRaw('DATE(created_at) as day, COUNT(*) as cnt')
->whereBetween('created_at', [
now()->subDays(30),
now()
])
->groupBy('day')
->orderBy('day')
->get();
比 PHP 循环查多张表快一个数量级,也比硬写 UNION 更易维护。
不要用 withCount 做日统计的三个原因
- withCount 没有 GROUP BY 能力,它只返回主模型 + 一个总数字段,无法拆解到每一天
-
闭包里不能引用时间字段做分组,
withCount(['orders' => fn($q) => $q->whereDate('created_at', '2026-10-15')])只能筛出某一天的记录,不能生成多行结果 -
字段名固定为
{relation}_count,无法映射成2026-10-15_count这类动态键
真正需要「按日展示关联数量」时,应放弃 withCount,改用原生聚合或子查询 JOIN。











