#sql #sql-server #subquery #inner-join #window-functions
#sql #sql-server #Подзапрос #внутреннее соединение #окно-функции
Вопрос:
У меня есть этот SQL-запрос:
SELECT
stu.sno, sname, cname
FROM
sc scc,
(SELECT AVG(sc.grade) AS avg_grade
FROM sc
GROUP BY sc.cno) AS avg_grades
INNER JOIN
course c ON c.cno = scc.cno
INNER JOIN
s stu ON stu.sno = scc.sno;
И возникает ошибка, что многосоставный идентификатор scc.cno
не может быть привязан. Я в замешательстве — кто-нибудь может мне помочь?
Комментарии:
1. Не смешивайте неявный и явный синтаксис соединения
2. Вероятно, вы предполагали
SELECT AVG(...)
, что подзапрос должен быть частьюSELECT
, а неFROM
.3. Действительно ли существует таблица с именем
s
? Или это должен быть псевдоним? И нет, где вы используете среднее значение в запросе верхнего уровня.4. sc представляет для выбора курса для студентов, и я хочу выбрать имя stu, оценка которого (сохраненная в таблице sc) в одном или нескольких курсах ниже средней оценки этого курса.
Ответ №1:
Не смешивайте неявные и явные объединения! На самом деле, не используйте неявные объединения: это архаичный синтаксис, который не должен появляться в новом коде.
Запятая в FROM
предложении должна (вероятно) быть CROSS JOIN
:
SELECT stu.sno, sname, cname
FROM sc scc
CROSS JOIN (SELECT AVG(sc.grade) AS avg_grade FROM sc GROUP BY sc.cno) AS avg_grades
INNER JOIN course c on c.cno = scc.cno
INNER JOIN s stu on stu.sno = scc.sno;
Обратите внимание, что для того, чтобы этот подзапрос был полезным, вам, вероятно, потребуется select
столбец avg_grade
. Я бы также рекомендовал добавлять к каждому столбцу префикс таблицы, к которой он принадлежит, чтобы устранить любую возможную двусмысленность.
Наконец: вы (вероятно) можете использовать оконные функции вместо подзапроса:
SELECT stu.sno, sname, cname, scc.
FROM (SELECT *, AVG(grade) OVER() avg_grade FROM sc) scc
INNER JOIN course c on c.cno = scc.cno
INNER JOIN s stu on stu.sno = scc.sno;
Ответ №2:
Предполагая объединение студентов и курсов по принципу «один ко многим» и объединенную таблицу курсов студентов (т. Е. sc
), Рассмотрим упрощенную агрегацию по объединенным таблицам. Обязательно всегда указывайте столбцы с псевдонимом, если запрос содержит больше, чем в таблице:
SELECT
s.sno AS student_number
, s.sname AS student_name
, c.cname AS course_name
, AVG(sc.grade) AS avg_grade
FROM
sc
INNER JOIN
course c ON c.cno = sc.cno
INNER JOIN
stu s ON s.sno = sc.sno
GROUP BY
s.sno
, s.sname
, c.cname