First approach (LEFT JOIN)
Execution Plan: First image shows statistics, an index is used when performing the above SQL, example created in MySQL-Fiddle. And second image for large data size, its around 8 million rows, and it takes a small amount of time to execute.
Now we will go for second approach (GROUP_CONCAT WITH SUBSTRING_INDEX)
Execution plan: First image show statistics taken from MySQL-Fiddle, used group-concat and substring-index both to calculate (min/max) value and/or other column of the table. Second image show that its also good time effective as it also takes a small amount of time to get min/max value and table size around 8 million rows.
MySQL Fiddle Link
SELECT s.Name,c1.Id AS Max_Score_ID,c1.Score as Max_Score FROM Students s LEFT JOIN Scores c1 ON (c1.Student=s.Id) LEFT JOIN Scores c2 ON ( c1.Student=c2.Student AND (c1.Score<c2.Score OR (c1.Score=c2.Score AND c1.Id<c2.Id)) ) WHERE c2.Score IS NULL ORDER BY c1.Score DESC;
Execution Plan: First image shows statistics, an index is used when performing the above SQL, example created in MySQL-Fiddle. And second image for large data size, its around 8 million rows, and it takes a small amount of time to execute.
Now we will go for second approach (GROUP_CONCAT WITH SUBSTRING_INDEX)
SELECT s.Name, CAST(SUBSTRING_INDEX( GROUP_CONCAT(c1.Id order by c1.Score desc),',',1 ) AS DECIMAL(10, 2)) AS Max_Score_ID, CAST(SUBSTRING_INDEX( GROUP_CONCAT(c1.Score order by c1.Score desc),',',1 ) AS DECIMAL(10, 2)) as Max_Score FROM Students s LEFT JOIN Scores c1 ON (c1.Student=s.Id) GROUP BY s.Id ORDER BY Max_Score DESC;
Execution plan: First image show statistics taken from MySQL-Fiddle, used group-concat and substring-index both to calculate (min/max) value and/or other column of the table. Second image show that its also good time effective as it also takes a small amount of time to get min/max value and table size around 8 million rows.
MySQL Fiddle Link