Использование SUM() в предложении ON соединения

У меня есть 3 таблицы с именами «студенты», «студент_курсы» и «оценки». И для каждого студента мне нужно рассчитать общий средний балл. Так что я немного застрял. :(

студенческий стол

Студенческий билет Имя ученика 77 Пепе ЛеПью

Student_courses

Студенческий билет ид_курса процент_класса 77 101 95,7 77 202 85,9 77 303 77,1 77 404 66,6

оценки

from_percent to_percent Letter_grade средний балл 0 69 Ф 0 70 72 С- 1,67 73 76 С 2.0 77 79 С+ 2.33 80 82 Б- 2,67 83 86 Б 3.0 87 89 B+ 3.33 90 92 А- 3,67 93 96 А 4.0 97 100 А+ 4.0

Вот мой запрос, который вызывает ошибку. (Код ошибки 1111. Недопустимое использование групповой функции) Я использую MySQL, но был бы рад получить стандартное решение SQL.

SELECT student_id, student_name,
(select g.GPA      
 from course_student AS cs    
 inner join Grades AS g ON (sum(cs.percent_grade) / count(*)) BETWEEN g.from_percent AND g.to_percent
 where cs.student_id = students.id) As GPA 
FROM students 

Ожидаемым результатом будет список всех учащихся в таблице учащихся и их соответствующий общий средний балл.

Студенческий билет средний балл 77 2,67

Обновление 1.

Я только что заставил его работать на одного студента. Но мне нужно, чтобы это работало для всех учеников в таблице студентов. Вот код для одного студента.

select g.GPA, g.from_percent, g.to_percent
 from course_student AS cs    
 inner join Grades AS g 
 where cs.student_id = 77
 group by g.GPA, g.from_percent, g.to_percent
 HAVING (sum(cs.percent_grade) / count(*)) BETWEEN g.from_percent AND g.to_percent 

Возможно, эта рабочий пример поможет нам совместно найти решение dbfiddle.uk/LqKCZTZl

Bart McEndree 17.04.2024 17:18

Пожалуйста, добавьте ожидаемый результат к вашему вопросу и объясните необходимую вам логику. Не пишите комментарии, вместо этого отредактируйте свой вопрос. Если вам нужно решение для разных учащихся, вам следует соответствующим образом добавить их в образец данных.

Jonas Metzler 17.04.2024 17:24

Данные таблицы примеров — это здорово, но минимально воспроизводимый пример также должен включать ожидаемый результат.

jarlh 17.04.2024 17:30

Обновил вопрос с таблицей ожидаемого результата. :) Спасибо

LostAndConfused 17.04.2024 17:32
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
4
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мы можем создать CTE StudentGrades, который группируется по студентам и рассчитывает среднюю оценку по всем их курсам. Затем мы можем использовать AvgGrade для объединения в таблице оценок.

WITH StudentGrades as
(
  SELECT s.student_id, s.student_name, SUM(percent_grade) as TotalGrade, count(*) as CourseCount, CAST(SUM(percent_grade) / count(*) AS INT)  as AvgGrade
  FROM students  s
  INNER JOIN student_courses c on s.student_id=c.student_id
  GROUP BY s.student_id, s.student_name
)
SELECT sg.student_id, sg.student_name, g.GPA
FROM StudentGrades sg
INNER JOIN grades g on g.from_percent <= sg.AvgGrade AND g.to_percent >= sg.AvgGrade

рабочий пример

Студенческий билет Имя ученика средний балл 69 Барт МакЭндри 4 77 Пепе ЛеПью 2,67

Великолепно. МОЙ уровень знаний SQL не простирается так далеко, поэтому я бы определенно не достиг этого самостоятельно. :) Отмечаем это как принятый ответ.

LostAndConfused 17.04.2024 17:36

Зачем такое странное разделение? Мы можем просто использовать AVG(percent_grade). Поскольку вы не проверяете, равны ли значения нулю, вы рискуете получить исключение.

Jonas Metzler 17.04.2024 17:49

В дизайне есть несколько ошибок. Зачем вообще нужен столбец GPA или таблица оценок? Разве AvgGrade не будет более точным? Если бы AvgGrade был равен 69,9, оценка не была бы найдена, поскольку нет записи, соответствующей этому значению. Вот почему я преобразовал его в INT.

Bart McEndree 17.04.2024 17:50

@Jonas Metzler Я придерживался стиля LostAndConfused и старался сохранить как можно больше от их оригинальной попытки. Ваше предложение — хороший шаг по оптимизации.

Bart McEndree 17.04.2024 17:51

@BartMcEndree Это не просто «оптимизация», это избежание возможных исключений деления на ноль. Я бы также внес некоторые другие изменения, поэтому расширил вашу скрипку: dbfiddle.uk/F-wShEA5 Обратите внимание, что я намерен просто улучшить ваш ответ, а не сказать, что он плохой. В любом случае ваш запрос находится на правильном пути. Может быть, вы могли бы посмотреть и подумать, полезно это или нет для вас/ОП.

Jonas Metzler 17.04.2024 18:01

Вы оба очень полезны. Спасибо. @Барт, я обновлю таблицу оценок, включив в нее 69,99, которые ты поймал. Я публиковал данные непосредственно от своих пользователей, не проводя по ним технической проверки. РЖУ НЕ МОГУ

LostAndConfused 17.04.2024 22:16

@Джонас, замечательное предложение. Прежде чем опубликовать его здесь, я несколько удалил SQL, что исключило возможность деления на ноль. Но тот факт, что это упрощает запрос, хорош, поскольку его легче читать и поддерживать.

LostAndConfused 17.04.2024 22:21

Другие вопросы по теме