Найти список топперов по каждому классу, если дать индивидуальные оценки по каждому предмету - PullRequest
0 голосов
/ 28 января 2020

Мне нужна помощь в написании эффективного запроса, чтобы найти список топеров (ученики с максимальным общим количеством баллов в каждом классе), когда нам дают индивидуальные оценки по каждому предмету в разных классах. Мы должны вернуть 3 столбца: класс, имя topper_student и topper_student_total.

Я использовал несколько подзапросов, чтобы найти решение. Я уверен, что для этой проблемы были бы гораздо лучшие реализации (возможно, через соединения или оконные функции?).

Таблица ввода и мое решение можно найти по ссылке SQL Fiddle.

http://www.sqlfiddle.com/#! 15 / 2919e / 1/0

Таблица ввода:

enter image description here

Ответы [ 3 ]

1 голос
/ 28 января 2020

Было бы яснее использовать временные таблицы для хранения результатов по пути и обеспечения возможности отслеживания результата, но решение может быть достигнуто с помощью одного запроса:

WITH student_marks AS (
    SELECT Class_num, Name, SUM(Marks) AS student_total_marks
    FROM School
    GROUP BY Class_num, Name
) 
SELECT Class_num, Name, student_total_marks 
FROM ( 
    SELECT Class_num, Name, student_total_marks, ROW_NUMBER() OVER(partition by Class_num order by student_total_marks desc, Class_num) AS beststudentfirst
    FROM student_marks
) A
WHERE A.beststudentfirst = 1

Запрос в операторе WITH вычисляет сумма баллов за каждого ученика в классе. На этом этапе subject больше не требуется. Результат временно сохраняется в student_marks .

. Далее нам нужно создать счетчик (beststudentfirst), используя ROW_NUMBER для нумерации итоговых оценок от самых высоких до самых низких в каждом классе (упорядочить по student_total_marks des c, Class_num). Счетчик следует перезапускать каждый раз при изменении класса (разделение по порядку Class_num).

Из этого последнего результата нам нужен только счетчик (beststudentfirst) со значением один. Это лучший ученик в каждом классе.

0 голосов
/ 28 января 2020

Оконные функции - самый естественный способ приблизиться к этому. Если вам всегда нужно ровно три студента, используйте row_number():

select Class_num, Name, total_marks
from (select name, class_num, sum(marks) as total_marks,
             row_number() over (partition by class_num order by sum(marks) desc) as seqnum
      from School
      group by Class_num, Name
     ) s
where seqnum <= 1
order by class_num, total_marks desc;

. Если вы хотите учесть галстуки, используйте rank() или dense_rank().

* 1009. * Здесь является SQL скрипкой.

0 голосов
/ 28 января 2020
select Class_num,[Name],total_marks from
(
select Row_number() over (partition by class_num order by Class_num,SUM(Marks) desc) as 
[RN],Class_num,[Name],SUM(Marks) as total_marks
from School
group by Class_num,[Name]
)A
where RN=1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...