Примечание. Я вполне уверен, что оптимизатор Oracle недостаточно наивен, чтобы генерировать подзапрос «ranked_students» ниже для каждой обновленной строки, но, конечно, всегда следует проверять свои оптимизации на значительных объемах данных. где это применимо, и используйте «объяснить план», чтобы решить, что лучше.
Мне кажется, что проблема с вашим запросом состоит в том, что функция rank () не производит функцию правильные результаты, потому что он смотрит только на одного студента за раз, и, следовательно, ранг этого студента всегда № 1 ... по отношению к себе!
Я также думаю, что вы, вероятно, хочу density_rank () в случае, если два студента имеют одинаковые средние баллы.
Итак, я сделал пример запроса, который использует предложение «with» для ранжирования всех студентов (у которых нет класс <60), а затем использует его для обновления таблицы student1. </p>
update student1
set student1.gpa = (
with ranked_students as
(
select student1.sno,
dense_rank() over (
order by sum(sc.grade*course.credit)/sum(course.credit) desc
) as gpa
from student1
join sc on sc.sno = student1.sno
join course on course.cno = sc.cno
where not exists (
select 1 from sc where sc.sno =student1.sno
and sc.grade < 60
)
group by student1.sno
)
select gpa from ranked_students r
where r.sno = student1.sno
);
select * from student1 order by gpa;
+-----+-------+-----+
| SNO | SNAME | GPA |
+-----+-------+-----+
| 002 | Alice | 1 |
| 001 | Bob | 2 |
| 003 | Mary | - |
+-----+-------+-----+
Вот инструкции для воссоздания моих таблиц тестирования:
create table sc as
select '001' as sno, 'C1' as cno, 80 as grade from dual
union select '001' as sno, 'C3' as cno, 70 as grade from dual
union select '002' as sno, 'C2' as cno, 90 as grade from dual
union select '003' as sno, 'C2' as cno, 59 as grade from dual
union select '003' as sno, 'C5' as cno, 98 as grade from dual;
create table student1 as
select '001' as sno, 'Bob' as sname, 100 as gpa from dual
union select '002' as sno, 'Alice' as sname, 100 as gpa from dual
union select '003' as sno, 'Mary' as sname, 100 as gpa from dual;
create table course as
select 'C1' as cno, 4 as credit from dual
union select 'C2' as cno, 4 as credit from dual
union select 'C3' as cno, 3 as credit from dual
union select 'C4' as cno, 3 as credit from dual
union select 'C5' as cno, 1 as credit from dual;
Приведенные выше таблицы описывают Алису a у нее высокий средний балл, у Боба - более низкий, а у Мэри - оценка ниже 60, что исключает ее из рейтинга.
Вот запрос, иллюстрирующий средние баллы среднего балла:
select student1.sno, student1.sname,
round(sum(sc.grade*course.credit)/sum(course.credit),0) as gpa
from student1
join sc on sc.sno = student1.sno
join course on course.cno = sc.cno
group by student1.sno, student1.sname
order by gpa desc;
+-----+-------+-----+
| SNO | SNAME | GPA |
+-----+-------+-----+
| 002 | Alice | 90 |
| 001 | Bob | 76 |
| 003 | Mary | 67 |
+-----+-------+-----+