在数据库的世界里,SQL是一种强大的查询语言,它允许以多种方式检索、分析和操作数据。今天,将通过一个有趣的SQL查询谜题来学习如何使用SQL来分析学生的成绩。假设被数学系主任要求提供三份学生成绩的排名列表:成绩在前25%的学生、成绩在后25%的学生以及处于中间的学生。将使用一个名为TestScore的表来进行查询,这个表包含了学生ID、学生姓名和成绩这三个字段。
为了更好地理解这个问题,首先需要创建一个包含测试数据的表。在实际的数据库操作中,通常会创建一个物理表并插入数据。但在这个例子中,为了简化操作,使用了一个表变量来存储数据。以下是插入数据的SQL代码:
DECLARE @TestScore TABLE (
StudentID int,
StudentName Varchar(40),
Score float
)
INSERT INTO @TestScore VALUES (1, 'Han Solo', 98.0);
INSERT INTO @TestScore VALUES (2, 'The Fly', 92.0);
INSERT INTO @TestScore VALUES (3, 'Darth Vader', 83.0);
INSERT INTO @TestScore VALUES (4, 'Luke Skywalker', 78.0);
INSERT INTO @TestScore VALUES (5, 'Homer Simpson', 54.0);
INSERT INTO @TestScore VALUES (6, 'Porky Pig', 65.0);
INSERT INTO @TestScore VALUES (7, 'James T. Kirk', 91.0);
INSERT INTO @TestScore VALUES (8, 'Spock', 93.0);
INSERT INTO @TestScore VALUES (9, 'Batman', 85.0);
INSERT INTO @TestScore VALUES (10, 'Robin', 87.0);
INSERT INTO @TestScore VALUES (11, 'Superman', 94.0);
INSERT INTO @TestScore VALUES (12, 'Road Runner', 74.0);
INSERT INTO @TestScore VALUES (13, 'Wilie Coyote', 79.0);
INSERT INTO @TestScore VALUES (14, 'Ant Man', 82.0);
INSERT INTO @TestScore VALUES (15, 'Cool Hand Luke', 92.0);
INSERT INTO @TestScore VALUES (16, 'C3PO', 88.0);
INSERT INTO @TestScore VALUES (17, 'BB8', 92.0);
INSERT INTO @TestScore VALUES (18, 'Flash Gordon', 60.0);
INSERT INTO @TestScore VALUES (19, 'Bugs Bunny', 84.0);
INSERT INTO @TestScore VALUES (20, 'Gordon Geko', 75.0);
接下来,将使用SQL查询来解决这个问题。首先,需要找出成绩在前25%的学生。这可以通过使用TOP PERCENT子句来实现。以下是相应的SQL查询:
SELECT TOP (25) PERCENT WITH TIES StudentName, Score
FROM @TestScore
ORDER BY Score DESC
这个查询按照成绩降序排列,确保了成绩最高的学生被列出。同时,使用了WITH TIES子句,以确保那些成绩与前25%学生相同的学生也被包括在内。
接下来,需要找出成绩在后25%的学生。这可以通过使用与前一个查询相同的查询,但是将成绩按升序排列来实现。以下是相应的SQL查询:
SELECT TOP (25) PERCENT WITH TIES StudentName, Score
FROM @TestScore
ORDER BY Score ASC
这个查询按照成绩升序排列,确保了成绩最低的学生被列出。
最后,需要找出处于中间的学生。这可以通过结合前两个查询的结果,然后使用子查询来排除这些学生来实现。以下是相应的SQL查询:
SELECT StudentName, Score
FROM @TestScore
WHERE StudentID NOT IN (
SELECT TOP (25) PERCENT WITH TIES StudentID
FROM @TestScore
ORDER BY Score DESC
UNION
SELECT TOP (25) PERCENT WITH TIES StudentID
FROM @TestScore
ORDER BY Score ASC
)
ORDER BY Score DESC;
也可以使用EXCEPT运算符来实现相同的结果,如下所示:
WITH TopAndBottomScore (StudentID, StudentName, Score)
AS (
SELECT TOP (25) PERCENT WITH TIES StudentID, StudentName, Score
FROM @TestScore
ORDER BY Score DESC
UNION
SELECT TOP (25) PERCENT WITH TIES StudentID, StudentName, Score
FROM @TestScore
ORDER BY Score ASC
)
SELECT StudentName, Score
FROM @TestScore
EXCEPT
SELECT StudentName, Score
FROM TopAndBottomScore
ORDER BY Score DESC;
在这个查询中,使用了一个公用表表达式(CTE)来包含顶部和底部成绩的联合。然后,使用EXCEPT运算符来从所有成绩中排除这些成绩。
作为额外的挑战,可以使用CUME_DIST窗口函数来计算成绩的相对位置。以下是相应的SQL查询:
WITH CumScore (StudentName, Score, CumScore)
AS (
SELECT StudentName,
Score,
CUME_DIST() OVER (ORDER BY Score) AS CumScore
FROM @TestScore
)
SELECT CASE
WHEN CumScore <= 0.25 THEN 'Bottom25'
WHEN CumScore >= 0.75 THEN 'TOP25'
ELSE 'Middle'
END as Ranking,
StudentName,
Score
FROM CumScore
ORDER BY Score;