2016-05-07 2 views
0

Можно ли ссылаться на встроенное представление, определенное в предложении FROM из подзапроса в предложении WHERE?SQL inline view subquery

SELECT tmp.TeacherName, 
     tmp.courseid, 
     tmp.AvgAttendingStudents 
FROM (SELECT T.TeacherID    AS ID, 
       T.TeacherName   AS Name, 
       C.CourseID    AS CourseID, 
       avg(L.AttendingStudents) AS AvgAttendingStudents 
     FROM Teachers AS T 
       join Courses AS C 
       ON C.TeacherID = T.TeacherID 
       join Lessons AS L 
       ON L.CourseID = C.CourseID 
     GROUP BY T.TeacherID, 
        C.CourseID) AS tmp 
WHERE tmp.AvgAttendingStudents = (SELECT max(AvgAttendingStudents) 
            FROM tmp AS tmp2 
            WHERE tmp2.TeacherID = tmp.TeacherID); 

В этом примере я пытаюсь перечислить все учитель, и для каждого из них я хочу показать ход, имеющим максимальные среднего числа посещающих студентов (в расчете на все уроки). Я попытался использовать встроенный просмотр (tmp), чтобы вычислить среднее число посещающих студентов для каждого курса, но я не знаю, могу ли я ссылаться на это представление в подзапросе SELECT max (...). Мне нужно это для работы с Oracle, но, к сожалению, на данный момент у меня нет базы данных Oracle, чтобы попробовать ее. Я пытался с MySQL (так как я не думаю, что я использую какие-либо функции, специфичные для Oracle), но, как и ожидалось, я получаю сообщение об ошибке «Таблица« db.tmp »не существует». Насколько это возможно с Oracle?

Вот мой пример схемы:

CREATE TABLE Courses 
    (
    CourseID INTEGER PRIMARY KEY, 
    CourseName VARCHAR(32), 
    TeacherID INTEGER 
); 

CREATE TABLE Teachers 
    (
    TeacherID INTEGER PRIMARY KEY, 
    TeacherName VARCHAR(32) 
); 

CREATE TABLE Lessons 
    (
    LessonDate  TIMESTAMP, 
    CourseID   INTEGER, 
    AttendingStudents INTEGER, 
    PRIMARY KEY (LessonDate, CourseID) 
); 

(Извините за мой плохой английский)

ответ

0

Вы правы в том, что вы не можете ссылаться на производную таблицу («встроенный вид») таким образом. Вам необходимо переписать производную таблицу («встроенный просмотр») в общее выражение таблицы:

У вас также есть другие ошибки. В производной таблице вы переименуете TeacherID в ID и TeacherName в Name, поэтому вам нужно использовать эти имена столбцов, а не «реальные».

Также Oracle не поддерживает AS для псевдонима таблицы, поэтому вам также нужно избавиться от них.

Так прямое переписывание заявления будет:

with tmp as (
    SELECT T.TeacherID    AS ID, 
     T.TeacherName   AS Name, 
     C.CourseID    AS CourseID, 
     avg(L.AttendingStudents) AS AvgAttendingStudents 
    FROM Teachers T 
     join Courses C 
      ON C.TeacherID = T.TeacherID 
     join Lessons L 
      ON L.CourseID = C.CourseID 
    GROUP BY T.TeacherID, 
      C.CourseID 
) 
SELECT tmp.name, 
     tmp.courseid, 
     tmp.AvgAttendingStudents 
FROM tmp 
where tmp.AvgAttendingStudents = (SELECT max(AvgAttendingStudents) 
            FROM tmp tmp2 
            WHERE tmp2.id = tmp.id); 

Однако выше будет не работы в Oracle из-за недопустимое использование функции group by и агрегатной. Выше приведет к «ORA-00979: Не GROUP BY выражение» см это SQLFiddle

Для этого, чтобы работать, вы должны использовать функцию окна в КТР и избавиться от group by:

with tmp as (
    SELECT T.TeacherID    AS ID, 
     T.TeacherName   AS Name, 
     C.CourseID    AS CourseID, 
     avg(L.AttendingStudents) over (partition by t.teacherid, c.courseid) AS avgattendingstudents 
    FROM Teachers T 
     join Courses C 
      ON C.TeacherID = T.TeacherID 
     join Lessons L 
      ON L.CourseID = C.CourseID 
) 
SELECT tmp.name, 
     tmp.courseid, 
     tmp.AvgAttendingStudents 
FROM tmp 
where tmp.AvgAttendingStudents = (SELECT max(AvgAttendingStudents) 
            FROM tmp tmp2 
            WHERE tmp2.id = tmp.id); 

См. Этот пример SQLFiddle.


Обратите внимание, что вы не можете проверить вышеуказанные вопросы с MySQL, потому что он не поддерживает modern SQL как общие табличные выражения или функции окна.

Но вы можете использовать примеры SQLFiddle для проверки его данными.

0

Вы можете использовать имеющий пункт, который может предоставить вам способ Constraint функцию agregate.

Вот пример:

SELECT T.TeacherID    AS ID, 
      T.TeacherName   AS Name, 
      C.CourseID    AS CourseID, 
      avg(L.AttendingStudents) AS AvgAttendingStudents 
    FROM Teachers AS T 
      join Courses AS C 
      ON C.TeacherID = T.TeacherID 
      join Lessons AS L 
      ON L.CourseID = C.CourseID 
    GROUP BY T.TeacherID, 
       T.TeacherName 
       C.CoursesID 
    HAVING avg(L.AttendingStudents) = (SELECT max(AvgAttendingStudents) 
           FROM Teachers AS tmp2 
           WHERE tmp2.TeacherID = T.TeacherID); 

Я просто удалить свой первый вложенный запрос и изменение AvgAttendingStudents Сред (L.AttendingStudents) (обусловленно вы не можете работать с переменной на Имея пункт) и добавить выбранные attributs в Групповое предложение, я не тестирую, но вот способ сделать трюк.

Не забудьте добавить свой непереработанный вар, выбранный в групповом предложении.

Здесь представлена ​​документация по having clause.

+0

В таблице 'учителей' нет столбца' AvgAttendingStudents'. И Oracle не поддерживает 'AS' для псевдонима таблицы. –