是否可以引用" FROM"中定义的内联视图?来自WHERE子句中的子查询的子句?
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的功能),但正如预期的那样,我得到了错误" Table' 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 :(得分:0)
您可以使用having子句,它可以为您提供约束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更改为avg(L.AttendingStudents)(因为你不能使用变量到Having子句)并在Group子句中添加选定的attributs,我不测试但是这里的方式做的伎俩。
不要忘记添加在group子句中选择的未经过聚集的var。
这是关于having clause的文档。
答案 1 :(得分:0)
你是对的,因为你不能以这种方式引用派生表("内联视图")。您需要将派生表("内联视图")重写为公用表表达式:
你还有其他错误。在派生表格中,您将TeacherID
重命名为ID
,将TeacherName
重命名为Name
,因此您需要使用这些列名而不是" real"那些。
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);
但是,由于group by
和聚合函数的使用无效,以上不在Oracle中有效。以上结果将导致" ORA-00979:不是GROUP BY表达式",请参阅此SQLFiddle
为此,您需要在CTE中使用窗口函数并摆脱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示例来测试数据。