Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

islamnouman's avatar

How to get user activity log with group by total duration of user for a date and for specific user id


user_id 					start				 		stop 
1 						8/04/2021 18:38:00 		8/04/2021 18:38:55 
1						8/04/2021 18:40:00 		8/04/2021 18:40:20 
6 						8/04/2021 18:38:00 		NULL 
2 						8/04/2021 18:40:00 		8/04/2021 18:40:20
2 						9/04/2021 14:54:00 		9/04/2021 14:55:00 
1 						9/04/2021 14:54:00 		9/04/2021 14:56:00 
6 						13/04/2021 15:01:00 	13/04/2021 16:00:00

expected result

0-
		-> 2021-04-08 //(date)
			0-
				 -> 1 //(user_id) 
					    0- 
							 -> 75 //(total duration of 2021-04-08 for user Id 1) 
									0-
										->  user_id =1 
											  start =8/04/2021 18:38:00 
											  end =8/04/2021 18:38:55
											  time diff = 55 
									 1-
										->  user_id =1 
										  	  start =8/04/2021 18:40:00 
											  end =8/04/2021 18:40:20 
											  time diff = 20 
			1-
				-> 2 //(user_id) 
					  0- 
						  -> 20 //(total duration of 2021-04-08 for user Id 2) 
									0- 
										->  user_id =2 
											  start =8/04/2021 18:40:00 
											  end =8/04/2021 18:40:20 
											  time diff = 20

1...>
2...>

how to get records with first of all group by date then group by user id then with time difference in seconds of single row and then sum of total time differences of all rows by user_id on each day and exclude row with null end time(e.g. as per i am sharing required expected result object) kindly share dynamic query so that conditions for filters could apply easily.

thanks in advance

0 likes
2 replies
psrz's avatar
psrz
Best Answer
Level 10

It's mostly "nested" group by and map using collection to get the result you want.

Not much mistery, you only need to go one step at a time, group by group

$result = ActivityLog::query()
        ->whereNotNull('start')
        ->whereNotNull('end')
        ->get()
        ->map(function($row) {
            $row->diffInseconds = $row->start->diffInseconds($row->end);
            return $row;
        })
        ->groupBy(fn ($row) => $row->start->format('Y-m-d'))
        ->map(function($dates) {
            return $dates
                ->groupBy('user_id')
                ->map(function($userEntries) {
                    $total = $userEntries->sum('diffInseconds');
                    return $userEntries
                        ->map(function($entry) use ($total) {
                            $entry->total = $total;
                            return $entry;
                        })
                        ->groupBy('total');
                });
        });

You could calculate the difference in seconds with the database using selectRaw().

If you make the calculation with php like here then make sure your activity log eloquent model has $casts of "start" and "end" as datetime, or that first map will blow up

1 like
islamnouman's avatar

@psrz thank you dear , working perfectly i am new in this field so I will be great-full if you could share any link for learning such a mastery in mysql an specially in laravel

Please or to participate in this conversation.