免责声明:我是一个SQL新手,这是一个类,但我真的可以用正确的方向戳。
我有这三张桌子:
student(_sid_, sname, sex, age, year, gpa)
section(_dname_, _cno_, _sectno_, pname)
enroll(_sid_, grade, _dname_, _cno_, _sectno_)
(由下划线表示的主键)
我正在尝试编写一个与Oracle兼容的SQL查询,该查询返回一个表,其中包含学生姓名(student.sname
),每个部分中的gpa最高(包括section.cno
和{{1} }}以及section.sectno
的所有其他属性。
我设法使用汇总查询和section
来获取每个部分的最大GPA:
GROUP BY
更别说其他 SELECT MAX(s.gpa), e.cno, e.sectno
FROM enroll e,
student s
WHERE s.sid = e.sid
GROUP BY e.cno, e.sectno
属性,我甚至无法弄清楚如何处理学生姓名(section
)。如果我将它添加到student.sname
子句中,它必须包含在SELECT
中,这会混淆查询的其余部分。如果我在外部查询的GROUP BY
或WHERE
子句中使用整个查询,我只能访问表中的三个字段,这没有多大用处。
我知道你不能给我确切的答案,但任何提示都会受到赞赏!
答案 0 :(得分:3)
假设Oracle 9i +,只有一名GPA最高的学生(如果有关系)使用:
WITH summary AS (
SELECT e.*,
s.name,
ROW_NUMBER() OVER(PARTITION BY e.cno, e.sectno
ORDER BY s.gpa DESC) AS rank
FROM ENROLL e
JOIN STUDENT s ON s.sid = e.sid)
SELECT s.*
FROM summary s
WHERE s.rank = 1
非CTE当量:
SELECT s.*
FROM (SELECT e.*,
s.name,
ROW_NUMBER() OVER(PARTITION BY e.cno, e.sectno
ORDER BY s.gpa DESC) AS rank
FROM ENROLL e
JOIN STUDENT s ON s.sid = e.sid) s
WHERE s.rank = 1
如果您想查看所有与GPA并列的学生,请使用:
WITH summary AS (
SELECT e.*,
s.name,
DENSE_RANK OVER(PARTITION BY e.cno, e.sectno
ORDER BY s.gpa DESC) AS rank
FROM ENROLL e
JOIN STUDENT s ON s.sid = e.sid)
SELECT s.*
FROM summary s
WHERE s.rank = 1
答案 1 :(得分:1)
提示:考虑到一个班级可能有不止一个GPA最高的学生。外部查询只需要三个字段。
答案 2 :(得分:0)
也许最短:
SELECT DISTINCT e.cno, e.sectno , e...,
FIRST_VALUE(s.sname) OVER
(PARTITION BY e.cno, e.sectno ORDER BY s.gpa DESC)
FROM enroll e,
student s
WHERE s.sid = e.sid
或
SELECT A.*
FROM
( SELECT s._sid, s.sname, e.cno, e.sectno ,..., s.gpa
MAX(s.gpa) OVER (PARTITION BY e.cno, e.sectno) AS maxgpa
FROM enroll e,
student s
WHERE s.sid = e.sid
) A
WHERE A.maxgpa = A.gpa
答案 3 :(得分:0)
以下是一些指示: -
希望这会有所帮助!!
答案 4 :(得分:0)
这应该可以满足您的需求。有关GPA按部分从最高到最低排名的详细信息,请参阅Oracle的RANK()函数。
<强>要求:强>
返回一个表格,其中包含学生姓名(student.sname),每个部分中的gpa最高(section.cno和section.sectno)以及部分中的所有其他属性。
SELECT * FROM
(
SELECT
s.sname,
s.gpa,
sec.dname,
sec.cno,
sec.sectno,
sec.pname,
/* for each "sec.cno, sec.sectno", this will rank each GPA in order from highest to lowest. Ties will have the same rank. */
RANK() OVER(PARTITION BY sec.cno, sec.sectno ORDER BY s.gpa DESC) as r_rank
FROM
enroll e,
student s,
section sec
WHERE
/* join enroll with student */
s.sid = e.sid
/* join section with enroll */
AND sec.dname = e.dname
AND sec.cno = e.cno
AND sec.sectno = e.sectno
)
WHERE r_rank = 1 /* this returns only the highest GPA (maybe multiple students) for each "sec.cno, sec.sectno" combination */
;
注意:如果您不想要领带,请将RANK()更改为ROW_NUMBER()
答案 5 :(得分:0)
虽然很久以后就回答了这个问题,但我仍想提出一个beautiful explanation,这对新手来说非常有用。 Introduction to SQL也有这样的规则。