Barney Vaughan Barney Vaughan - 3 months ago 6
PHP Question

Most efficient way to turn query a MySQL table to return a list grouped by the User ID & By Date (in PHP)

So I've got a table that looks like so:

╔═════════╦══════════════════════╦════════════╗
║ User_id ║ Start_date ║ Review_id ║
╠═════════╬══════════════════════╬════════════╣
║ 1 ║ 26/08/2016 17:32:42 ║ 150 ║
║ 1 ║ 26/07/2016 16:23:42 ║ 149 ║
║ 2 ║ 26/07/2016 14:13:42 ║ 148 ║
║ 3 ║ 26/06/2016 12:32:42 ║ 147 ║
║ 1 ║ 26/06/2016 12:32:42 ║ 146 ║
║ 1 ║ 26/06/2016 12:33:42 ║ 145 ║
║ 2 ║ 24/06/2016 14:33:42 ║ 144 ║
║ 2 ║ 23/06/2016 12:33:42 ║ 143 ║
╚═════════╩══════════════════════╩════════════╝


Which could end up being hundreds of entries long. What I need to do is return a table that can tell me how many reviews were completed in each month by each user.

I've tried returning the whole list of reviews and ordering them via PHP but I can't for the life of my figure out how to end up with something that looks like so:

╔═════════╦══════════════════════╗
║ User_id ║ Date ║ # Reviews ║
╠═════════╬══════════════════════╣
║ 1 ║ 08/2016 ║ 1 ║
║ 1 ║ 07/2016 ║ 1 ║
║ 1 ║ 06/2016 ║ 2 ║
║ 2 ║ 07/2016 ║ 1 ║
║ 2 ║ 06/2016 ║ 2 ║
║ 3 ║ 06/2016 ║ 1 ║
... ... ...


My approach originally was to search the Database for all the Reviews that occurred. Then parse them by PHP (saves putting all the strain on the DB for grouping). I've managed to group by ID using the following:

//List of the users - returned from DB
$userList = array(1,2,3);
//List of all the reviews - returned from DB
$reviewList = array(
[0] => array("user_id" => 1, "start_date"=> 26/08/2016 17:32:42),
[1] => ...);

foreach ($userList as $user){
foreach ($reviewList as $review){
if($review['user_id'] == $user){
$reviewarray[$user] = $reviewarray[$user] + 1;
}

}
}


But I'm a very sure it's not the most efficient way. It also doesn't parse by date, which is where I'm stuck.

I appreciate what I've provided isn't quite the finished article but all other routes I've taken have ended up with a very result. Let me know if you need more information.

Answer

I don't think you either need or should be doing such aggregations in your PHP code. Instead, let MySQL do this work for you; it was designed for this.

You can do a GROUP BY query using the user's ID and month-year combination as groups.

SELECT User_id,
       DATE_FORMAT(Start_date, '%Y-%m'),
       COUNT(*) AS `# Reviews`
FROM yourTable
GROUP BY User_id,
         DATE_FORMAT(Start_date, '%Y-%m')