Laravel中如何获取过去7天每日用户占比(重点关注最后一天)
过去7天每日用户数及占比查询优化方案
你的现有查询已经能获取基础的每日用户数,但存在两个核心问题:一是可能因时间范围边界遗漏数据,二是未计算占比、也未处理无用户日期的缺失情况。以下是完善后的实现方案:
1. 修正基础查询,确保时间范围准确
原查询的where('created_at', '>')会漏掉一周前当天0点前的用户,改用whereBetween锁定精确的7天范围(从7天前凌晨到当前深夜):
use Carbon\Carbon; use App\Models\User; $startDate = Carbon::now()->subDays(7)->startOfDay(); $endDate = Carbon::now()->endOfDay(); // 获取有用户注册的日期及对应数量 $dailyUsers = User::selectRaw('DATE(created_at) as date, COUNT(*) as count') ->whereBetween('created_at', [$startDate, $endDate]) ->groupBy('date') ->get() ->keyBy('date'); // 按日期键名存储,方便后续补全空日期
2. 补全7天内的所有日期(含无用户的日期)
如果某天没有新用户,原查询不会返回该日期记录,需要生成完整的7天日期序列并补全数据:
// 生成过去7天的完整日期数组 $dateRange = []; for ($i = 6; $i >= 0; $i--) { $date = Carbon::now()->subDays($i)->format('Y-m-d'); $dateRange[$date] = [ 'date' => $date, 'count' => $dailyUsers->has($date) ? $dailyUsers[$date]['count'] : 0 ]; } // 转成集合方便后续处理 $dailyUsersWithAllDates = collect($dateRange)->values();
3. 计算每日占比及提取最后一天数据
基于过去7天的总用户数计算每日占比,并单独提取最后一天的重点数据:
// 计算过去7天的总用户数 $totalUsers = $dailyUsersWithAllDates->sum('count'); // 计算每日占比(保留2位小数) $dailyUsersWithRatio = $dailyUsersWithAllDates->map(function ($item) use ($totalUsers) { $item['ratio'] = $totalUsers > 0 ? round(($item['count'] / $totalUsers) * 100, 2) : 0; return $item; }); // 提取最后一天的详细数据(直接取集合最后一个元素) $lastDayData = $dailyUsersWithRatio->last();
整合后的完整代码
use Carbon\Carbon; use App\Models\User; // 定义精确的7天时间范围 $startDate = Carbon::now()->subDays(7)->startOfDay(); $endDate = Carbon::now()->endOfDay(); // 查询有用户注册的日期数据 $dailyUsers = User::selectRaw('DATE(created_at) as date, COUNT(*) as count') ->whereBetween('created_at', [$startDate, $endDate]) ->groupBy('date') ->get() ->keyBy('date'); // 补全7天内的所有日期,处理无用户的情况 $dateRange = []; for ($i = 6; $i >= 0; $i--) { $date = Carbon::now()->subDays($i)->format('Y-m-d'); $dateRange[$date] = [ 'date' => $date, 'count' => $dailyUsers->has($date) ? $dailyUsers[$date]['count'] : 0 ]; } $dailyUsersWithAllDates = collect($dateRange)->values(); // 计算总用户数和每日占比 $totalUsers = $dailyUsersWithAllDates->sum('count'); $dailyUsersWithRatio = $dailyUsersWithAllDates->map(function ($item) use ($totalUsers) { $item['ratio'] = $totalUsers > 0 ? round(($item['count'] / $totalUsers) * 100, 2) : 0; return $item; }); // 获取最后一天的重点数据 $lastDayData = $dailyUsersWithRatio->last(); // 可直接输出或使用结果 // dd($dailyUsersWithRatio, $lastDayData);
关键细节说明
- 用
startOfDay()和endOfDay()确保时间范围精确到天,避免因时分秒遗漏数据 - 补全空日期保证数据的完整性,不会出现某天无用户时断档的情况
- 占比计算加入了总用户数为0的判断,避免除以0的错误
- 单独提取最后一天数据,方便你直接重点关注
内容的提问来源于stack exchange,提问作者Michael Adepoju
相关产品推荐
相关产品推荐

