谪仙阁-记录美好瞬间

数据库上机答案

作者头像
谪仙 本文作者

2025-9-22 阅读 169 约 19分钟读完

评论0

新建文件夹.zip

好——下面给你每题对应的 T-SQL(SQL Server)答案。我假设你是在 SQL Server 上运行(语句用到 GETDATE()CAST、窗口函数/子查询等),并且统一使用下面的 年龄计算表达式(精确到生日):

-- 年龄表达式(可直接复制到下面的查询里)
DATEDIFF(year, sbirth, GETDATE())
- CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END

关于 ssex 的说明:你的数据里 ssex 的编码在示例里好像不一致(0/1 与性别的对应不明确)。下面的查询里我会在涉及“女生/男生”的题目处写成 ssex = 0(你若实际 0=男、1=女,请把条件反过来即可)。

下面按题号给出 SQL 语句(每条独立可执行):


  1. 查询全体学生的学号、姓名与年龄
SELECT sno, sname,
  DATEDIFF(year, sbirth, GETDATE())
  - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END AS age
FROM StuInfo.dbo.S;
  1. 查询计算机系(sdept='计算机')的学生学号、姓名
SELECT sno, sname
FROM StuInfo.dbo.S
WHERE LTRIM(RTRIM(sdept)) = N'计算机';
  1. 查询计算机系所有的女生姓名和年龄(假设 ssex = 0 表示女;若你系统相反请改为 ssex = 1
SELECT sname,
  DATEDIFF(year, sbirth, GETDATE())
  - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END AS age
FROM StuInfo.dbo.S
WHERE LTRIM(RTRIM(sdept)) = N'计算机'
  AND ssex = 0;
  1. 查询选修了课程的学生学号(去重)
SELECT DISTINCT sno
FROM StuInfo.dbo.SC;
  1. 查询所有年龄在30岁以下的学生姓名及其年龄
SELECT sname,
  DATEDIFF(year, sbirth, GETDATE())
  - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END AS age
FROM StuInfo.dbo.S
WHERE (DATEDIFF(year, sbirth, GETDATE())
       - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END) < 30;
  1. 查询考试有不及格(还包括未参加考试,即 grade < 60 OR grade IS NULL)的学生的学号
SELECT DISTINCT sno
FROM StuInfo.dbo.SC
WHERE grade < 60 OR grade IS NULL;
  1. 查询年龄在25-30岁之间(包含25和30岁)的学生的姓名和年龄
SELECT sname,
  DATEDIFF(year, sbirth, GETDATE())
  - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END AS age
FROM StuInfo.dbo.S
WHERE (DATEDIFF(year, sbirth, GETDATE())
       - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END) BETWEEN 25 AND 30;
  1. 查询计算机,数学系和信息系学生的姓名
SELECT sname, sdept
FROM StuInfo.dbo.S
WHERE LTRIM(RTRIM(sdept)) IN (N'计算机', N'数学', N'信息工程', N'信息'); -- 兼顾可能的写法
  1. 查询不是计算机和信息工程系的学生姓名
SELECT sname, sdept
FROM StuInfo.dbo.S
WHERE LTRIM(RTRIM(sdept)) NOT IN (N'计算机', N'信息工程');
  1. 查询所有姓刘的学生姓名、学号
SELECT sno, sname
FROM StuInfo.dbo.S
WHERE sname LIKE N'刘%';
  1. 查询与数据库相关课程的课程号和名称(模糊匹配“数据库”)
SELECT cno, cname
FROM StuInfo.dbo.C
WHERE cname LIKE N'%数据库%';
  1. 查询未录入成绩的学生的学号和相应的课程号(grade IS NULL)
SELECT sno, cno
FROM StuInfo.dbo.SC
WHERE grade IS NULL;
  1. 查询计算机系年龄在30岁以下的学生姓名
SELECT sname
FROM StuInfo.dbo.S
WHERE LTRIM(RTRIM(sdept)) = N'计算机'
  AND (DATEDIFF(year, sbirth, GETDATE())
       - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END) < 30;
  1. 查询选修了0102号课程的学生学号及其成绩,按学号升序
SELECT sno, grade
FROM StuInfo.dbo.SC
WHERE cno = '0102'
ORDER BY sno ASC;
  1. 查询选修了0101号课程的学生学号及其成绩,按分数降序排列
SELECT sno, grade
FROM StuInfo.dbo.SC
WHERE cno = '0101'
ORDER BY grade DESC;
  1. 查询学生总人数
SELECT COUNT(*) AS total_students
FROM StuInfo.dbo.S;
  1. 查询选修了课程的学生人数(去重学号计数)
SELECT COUNT(DISTINCT sno) AS students_who_taken_course
FROM StuInfo.dbo.SC;
  1. 计算0101号课程的平均成绩(排除 NULL)
SELECT AVG(CAST(grade AS FLOAT)) AS avg_grade_0101
FROM StuInfo.dbo.SC
WHERE cno = '0101' AND grade IS NOT NULL;
  1. 计算计算机系学生的平均年龄
SELECT AVG(
  DATEDIFF(year, sbirth, GETDATE())
  - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END
) AS avg_age
FROM StuInfo.dbo.S
WHERE LTRIM(RTRIM(sdept)) = N'计算机';
  1. 查询选修了0102号课程的学生最低分数
SELECT MIN(grade) AS min_grade_0102
FROM StuInfo.dbo.SC
WHERE cno = '0102' AND grade IS NOT NULL;
  1. 查询学生 001108 选修课程的总学分数(若要只统计已录成绩的课可加 AND sc.grade IS NOT NULL
SELECT s.sno,
       SUM(COALESCE(c.ccredit,0)) AS total_credits
FROM StuInfo.dbo.SC sc
JOIN StuInfo.dbo.C c ON sc.cno = c.cno
JOIN StuInfo.dbo.S s ON sc.sno = s.sno
WHERE sc.sno = '001108'
GROUP BY s.sno;
  1. 查询每门课程号及其对应的选课人数
SELECT sc.cno, COUNT(sc.sno) AS student_count
FROM StuInfo.dbo.SC sc
GROUP BY sc.cno;
  1. 计算每门课程及其平均分(排除 NULL)
SELECT c.cno, c.cname, AVG(CAST(sc.grade AS FLOAT)) AS avg_grade
FROM StuInfo.dbo.C c
LEFT JOIN StuInfo.dbo.SC sc ON c.cno = sc.cno AND sc.grade IS NOT NULL
GROUP BY c.cno, c.cname;
  1. 计算选修了3门课程以上的学生学号(题目要求“超过3门”)
SELECT sno
FROM StuInfo.dbo.SC
GROUP BY sno
HAVING COUNT(*) > 3;
  1. 查询每个学生的学号及课程的平均分
SELECT sc.sno, AVG(CAST(sc.grade AS FLOAT)) AS avg_grade
FROM StuInfo.dbo.SC sc
WHERE sc.grade IS NOT NULL
GROUP BY sc.sno;
  1. 查询所有课程的平均学分
SELECT AVG(CAST(ccredit AS FLOAT)) AS avg_credit
FROM StuInfo.dbo.C;
  1. 查询与“林一帆”在同一个系学习的学生学号和姓名(不包括林一帆本人)
SELECT s2.sno, s2.sname
FROM StuInfo.dbo.S s1
JOIN StuInfo.dbo.S s2 ON LTRIM(RTRIM(s1.sdept)) = LTRIM(RTRIM(s2.sdept))
WHERE s1.sname = N'林一帆' AND s2.sno <> s1.sno;
  1. 查询平均分在75分以下的学生信息(学号、姓名、平均分)
SELECT t.sno, s.sname, t.avg_grade
FROM (
    SELECT sno, AVG(CAST(grade AS FLOAT)) AS avg_grade
    FROM StuInfo.dbo.SC
    WHERE grade IS NOT NULL
    GROUP BY sno
) t
JOIN StuInfo.dbo.S s ON s.sno = t.sno
WHERE t.avg_grade < 75;
  1. 查询选修0101号课程且成绩在80分以上的所有学生姓名、学号
SELECT s.sno, s.sname, sc.grade
FROM StuInfo.dbo.SC sc
JOIN StuInfo.dbo.S s ON sc.sno = s.sno
WHERE sc.cno = '0101' AND sc.grade >= 80;
  1. 查询每个学生的学号、姓名、选修的课程名及其成绩
SELECT s.sno, s.sname, c.cname, sc.grade
FROM StuInfo.dbo.S s
LEFT JOIN StuInfo.dbo.SC sc ON s.sno = sc.sno
LEFT JOIN StuInfo.dbo.C c ON sc.cno = c.cno
ORDER BY s.sno;
  1. 显示每个系的学生的平均年龄
SELECT LTRIM(RTRIM(sdept)) AS department,
       AVG(
         DATEDIFF(year, sbirth, GETDATE())
         - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END
       ) AS avg_age
FROM StuInfo.dbo.S
GROUP BY LTRIM(RTRIM(sdept));
  1. 查询“计算机”系所有选修了“数据库原理”课程的学生姓名
    (假设课程名包含“数据库原理”,或你也可直接用 cno = '0106')
SELECT DISTINCT s.sno, s.sname
FROM StuInfo.dbo.S s
JOIN StuInfo.dbo.SC sc ON s.sno = sc.sno
JOIN StuInfo.dbo.C c ON sc.cno = c.cno
WHERE LTRIM(RTRIM(s.sdept)) = N'计算机'
  AND c.cname LIKE N'%数据库原理%';
  1. 显示至少有5名学生选修的课程的平均分数及其课程名称
SELECT c.cno, c.cname, AVG(CAST(sc.grade AS FLOAT)) AS avg_grade, COUNT(sc.sno) AS student_count
FROM StuInfo.dbo.C c
JOIN StuInfo.dbo.SC sc ON c.cno = sc.cno AND sc.grade IS NOT NULL
GROUP BY c.cno, c.cname
HAVING COUNT(sc.sno) >= 5;
  1. 查询每个人选修的课程数,显示其学号及课程数
SELECT s.sno, s.sname, COUNT(sc.cno) AS course_count
FROM StuInfo.dbo.S s
LEFT JOIN StuInfo.dbo.SC sc ON s.sno = sc.sno
GROUP BY s.sno, s.sname;
  1. 查询有3门(包含3门)以上课程是70分以上(包含70分)的学生的学号及课程数
SELECT sno, COUNT(*) AS count_ge_70
FROM StuInfo.dbo.SC
WHERE grade >= 70
GROUP BY sno
HAVING COUNT(*) >= 3;
  1. 查询“C++程序设计”这门课程的学生成绩(先找课程号,再查)
-- 方法一:按课程名模糊匹配
SELECT sc.sno, s.sname, sc.grade
FROM StuInfo.dbo.SC sc
JOIN StuInfo.dbo.C c ON sc.cno = c.cno
JOIN StuInfo.dbo.S s ON sc.sno = s.sno
WHERE c.cname LIKE N'%C++程序设计%';
  1. 求年龄大于学生平均年龄的男学生姓名和年龄(假设 ssex = 1 表示男;若反过来改条件)
;WITH Ages AS (
  SELECT sno, sname,
    DATEDIFF(year, sbirth, GETDATE())
    - CASE WHEN DATEADD(year, DATEDIFF(year, sbirth, GETDATE()), sbirth) > GETDATE() THEN 1 ELSE 0 END AS age
  FROM StuInfo.dbo.S
)
SELECT a.sno, a.sname, a.age
FROM Ages a
CROSS JOIN (SELECT AVG(age) AS avg_age FROM Ages) av
WHERE a.age > av.avg_age
  AND EXISTS (SELECT 1 FROM StuInfo.dbo.S s WHERE s.sno = a.sno AND s.ssex = 1);
  1. 查询成绩高于该门课程平均分的学生学号和课程号
SELECT sc.sno, sc.cno, sc.grade
FROM StuInfo.dbo.SC sc
WHERE sc.grade IS NOT NULL
  AND sc.grade >
      (SELECT AVG(CAST(grade AS FLOAT)) FROM StuInfo.dbo.SC WHERE cno = sc.cno AND grade IS NOT NULL);
  1. 查询每门课程最高分的学生学号和课程号
SELECT sc.cno, sc.sno, sc.grade
FROM StuInfo.dbo.SC sc
JOIN (
    SELECT cno, MAX(grade) AS max_grade
    FROM StuInfo.dbo.SC
    GROUP BY cno
) m ON sc.cno = m.cno AND sc.grade = m.max_grade;
  1. 查询每门课程最低分的学生学号
SELECT sc.cno, sc.sno, sc.grade
FROM StuInfo.dbo.SC sc
JOIN (
    SELECT cno, MIN(grade) AS min_grade
    FROM StuInfo.dbo.SC
    WHERE grade IS NOT NULL
    GROUP BY cno
) m ON sc.cno = m.cno AND sc.grade = m.min_grade;
  1. 查询每门课程的最低分及其课程名称
SELECT c.cno, c.cname, m.min_grade
FROM StuInfo.dbo.C c
JOIN (
    SELECT cno, MIN(grade) AS min_grade
    FROM StuInfo.dbo.SC
    WHERE grade IS NOT NULL
    GROUP BY cno
) m ON c.cno = m.cno;
  1. 查询所有学生及其选修课程的课程名称、成绩(若未选课仍显示学生)
SELECT s.sno, s.sname, c.cname, sc.grade
FROM StuInfo.dbo.S s
LEFT JOIN StuInfo.dbo.SC sc ON s.sno = sc.sno
LEFT JOIN StuInfo.dbo.C c ON sc.cno = c.cno
ORDER BY s.sno;
  1. 显示所有课程的成绩,按照课程号升序排列,成绩降序排列(观察 NULL 排序位置)
SELECT sc.cno, sc.sno, sc.grade
FROM StuInfo.dbo.SC sc
ORDER BY sc.cno ASC, sc.grade DESC;

备注:在 SQL Server 中 NULLORDER BY ... DESC 时通常会被排在最后还是最前取决于版本/实现,可通过 ORDER BY sc.cno, CASE WHEN sc.grade IS NULL THEN 1 ELSE 0 END ASC, sc.grade DESC 明确控制 NULL 显示在前或后。


如果你要我:

  • 把这些 SQL 放到一个 .sql 文件里(按题号注释分组),我可以直接把整理好的文本给你;
  • 或者把某几题改成更“严格”的实现(例如:只统计已登记学分、只统计已录成绩、或按 sdept 的不同写法兼容)——告诉我你想要的格式,我直接改好给你。

另外提醒两点:

  1. 上面含有若干处对 sdeptsnamecname 的字符串匹配,我用了 LTRIM(RTRIM(...))LIKE 来提高鲁棒性;
  2. 关于 ssex 的编码(男/女 对应 0/1)如前所述不一致的话请按你数据实际值把 ssex = 0 / = 1 对调——我可以帮你统一检查并修正条件。

要我直接把这些查询打包成一个带注释的 .sql 文件吗?还是先把哪几题的输出示例跑一遍(给出预期结果示例)?



手机扫码阅读
上一篇 数据库上机2 下一篇 数据库上机
评论