попробуйте это.
$joinQuery = "(".DB::table('user_sessions')
->selectRaw('MIN(created_at) AS MinCreatedAt, user_id')
->groupBy('user_id')->toSql().") as us2" ;
$users = DB::table('user_sessions')
->selectRaw("user_sessions.os, COUNT(*)")
->join(DB::raw($joinQuery), function ($join) {
$join->on('user_sessions.created_at', '=', 'us2.MinCreatedAt')->on('user_sessions.user_id', '=', 'us2.user_id');
})
->groupBy('user_sessions.os');
Обновление
$q1 = self::select(DB::raw('MIN(created_at) as MinCreatedAt, user_id'))->groupBy('user_id');
$q2 = self::select(DB::raw('user_sessions.os, count(*)'));
$users = $q2->joinSub($q1, 'us2', function ($join) {
$join->on('user_sessions.created_at = us2.MinCreatedAt AND user_sessions.user_id = us2.user_id ');
})->groupBy('user_sessions.os')->get();