È stato impegnativo.
Per risolverlo ho usato diversi metodi:
- Una dichiarazione CASE per convertire in punti il posto del gruppo tra i primi 3.
- Numerazione delle righe con una variabile .
- INTERIORE E SINISTRA ISCRIVITI per unire i risultati.
La seguente query è stata testata sul tuo violino e funziona:
SELECT t1.`id`, t1.`name`, t1.`group1`,
t1.`section`, t1.`MARKS`, `t_group_points`.`points`
FROM `students` t1
#--- Join groups' points to the students
LEFT JOIN (
(
#---- Join all groups and give points to top 3 avg's groups ----
SELECT `t4`.`group1`, `t_points`.`points`
FROM (SELECT `t3`.`group1`, AVG(`t3`.`marks`) AS `avg`
FROM `students` `t3`
WHERE (`t3`.`section` = 'class1') AND
(`t3`.`group1` IS NOT NULL)
GROUP BY `t3`.`group1`) `t4`
INNER JOIN (
#---------- Select top 3 avarages ----------
(SELECT `top`.`avg`,
#-- Convert row number to points ---
CASE @curRow := @curRow + 1
WHEN '1' THEN 5
WHEN '2' THEN 3
WHEN '3' THEN 1
ELSE NULL END 'points'
FROM (SELECT DISTINCT `t_avg`.`avg`
FROM (SELECT `t2`.`group1`, AVG(`t2`.`marks`) AS `avg`
FROM `students` `t2`
WHERE (`t2`.`section` = 'class1') AND
(`t2`.`group1` IS NOT NULL)
GROUP BY `group1`) `t_avg`
ORDER BY `avg` DESC
LIMIT 0, 3) `top`, (SELECT @curRow:=0) r
) AS `t_points`)
ON (`t_points`.`avg` = `t4`.`avg`)
) AS `t_group_points`)
ON (`t_group_points`.`group1` = `t1`.`group1`)