共有三个表:
关于学生的表格:
s41071030(sno, sname, ssex, sage, sdept)
课程表:
c41071030(cno, cname, cpno, credit)
关于选择课程的表格:
sc41071030(sno, cno, grade)
现在,我想选择一个学生的详细信息sdept='CS'
,他或她选择了部门中最多的课程'CS'
。
共有三个表:
关于学生的表格:s41071030(sno, sname, ssex, sage, sdept)
课程表:c41071030(cno, cname, cpno, credit)
关于选择课程的表格:sc41071030(sno, cno, grade)
现在,我想选择一个学生的详细信息sdept='CS'
,他或她选择了部门中最多的课程'CS'
。
聚合sc41071030
行以获取计数。
将结果加入s41071030
到:
过滤行sdept
;
获取学生详细信息;
RANK()
计数值上的连接行。
选择排名为 1 的行。
WITH
aggregated AS (
SELECT
sno,
COUNT(*) AS coursecount
FROM
sc41071030
GROUP BY
sno
),
ranked AS (
SELECT
s.*,
RANK() OVER (ORDER BY agg.coursecount DESC) AS rnk
FROM
s41071030 s
INNER JOIN aggregated agg ON s.sno = agg.sno
WHERE
s.sdept = 'CS'
)
SELECT
sno,
sname,
ssex,
sage,
sdept
FROM
ranked
WHERE
rnk = 1
;
与任何适度复杂的 SQL 语句一样,最好执行“TDQD”——测试驱动查询设计。从问题的简单部分开始,然后将它们构建成更复杂的答案。
要了解计算机系每个学生上多少门课程,我们写道:
SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno;
我们现在需要找到 NumCourses 的最大值:
SELECT MAX(NumCourses) MaxCourses
FROM (SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
现在我们需要将该结果与子查询连接起来,所以是时候使用 CTE(公共表表达式)了:
WITH N AS
(SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
SELECT N.Sno
FROM N
JOIN (SELECT MAX(NumCourses) MaxCourses FROM N) M
ON M.MaxCourses = N.NumCourses;
我们需要获取学生详细信息,因此我们将其与学生表连接:
WITH N AS
(SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
SELECT S.*
FROM s41071030 S
JOIN N ON N.Sno = S.Sno
JOIN (SELECT MAX(NumCourses) MaxCourses FROM N) M
ON M.MaxCourses = N.NumCourses;
轻微测试的 SQL:你被警告了。要进行测试,请运行组件查询,确保每次都能获得合理的结果。在前一个查询正常工作之前,不要继续下一个查询。
请注意,课程表对您正在解决的查询并不重要。
另请注意,如果事实证明有几个学生都参加了相同数量的课程,并且该数字是任何学生正在学习的最大数量,则这可能会返回几行。(因此,如果有 3 名学生每人选修 7 门课程,并且没有学生选修超过 7 门课程,那么您将在结果集中看到 3 行。)