SQL练习题

  • 友情链接
    • 1、医疗信息管理系统数据库--MySQL
    • 2、邮件管理数据库设计--MySQL
    • 3、SQL Server医疗信息管理系统数据库【英文版-源码】--(Medical Management System Database)
    • 4、SQL Server电影院数据库管理系统【英文版-源码】--(Movie Theatre Management System Database)
  • 一、MySQL基础知识点总结
  • 二、学生成绩管理系统数据库设计
    • 1.项目背景及需求分析
    • 2.概念结构设计
    • 3.逻辑结构设计
    • 4.物理设计和实施
      • 4.1 SQL练习数据库及表创建
        • MySQL版本:8.0.20
      • 4.2 SQL练习表数据
      • 4.3 精选36道SQL查询练习题及答案解析
      • 4.3.1 练习题
        • 4.3.1.1. 连接查询 - 4题
        • 4.3.1.2. 子查询、连接查询 - 4题
        • 4.3.1.3. 聚合分组、连接查询 - 8题
        • 4.3.1.4. if 或 case 语句 - 2题
        • 4.3.1.5. 时间函数 - 6题
        • 4.3.1.6.综合应用 - 12题
      • 4.3.2 - 答案及解析
        • 4.3.2.1 连接查询 - 4题
        • 4.3.2.2 子查询、连接查询 - 4题
        • 4.3.2.3 聚合分组、连接查询 - 8题
        • 4.3.2.4 if 或 case 语句 - 2题
        • 4.3.2.5 时间函数 - 6题
        • 4.3.2.6 综合应用 - 12题
      • 4.4 创建一个学生视图,要求显示学生学号、姓名、班级、性别、专业、各科成绩、平均分、总分
      • 4.5 创建函数
        • 4.5.1 创建一个通过学号sid获取学生信息的函数
        • 4.5.2 自定义函数 2:要求函数体中包含其中一种流程控制语句,要求输入学生学号sid、课程编号,显示学生姓名、课程名称、成绩是否及格(即成绩>=60)
      • 4.6 创建存储过程
        • 4.6.1 学生每选修一门课,如果该门课程成绩达到60分及以上,则把该门课程学分加到学生学分里面,输出该学生姓名、学分
      • 4.7 创建触发器
        • 4.7.1 创建一个更新学生学分的触发器,如果该学生分数>=60,则给该学生加上这门课的学分
  • 三、知识点
    • 1. in 和 exists 的用法和区别
    • 2. rank() 与 dense_rank() 用法
    • 3. 数据库关系代数表达式学习

友情链接

1、医疗信息管理系统数据库–MySQL

医疗信息管理系统数据库–MySQL

2、邮件管理数据库设计–MySQL

邮件管理数据库设计–MySQL

3、SQL Server医疗信息管理系统数据库【英文版-源码】–(Medical Management System Database)

SQL Server医疗信息管理系统数据库【英文版-源码】–(Medical Management System Database)

4、SQL Server电影院数据库管理系统【英文版-源码】–(Movie Theatre Management System Database)

SQL Server电影院数据库管理系统【英文版-源码】–(Movie Theatre Management System Database)

一、MySQL基础知识点总结

对网络上流传的50道SQL练习题做了筛选,去掉了一些重复的题,剩下36道,总结分为6大类,几乎囊括了SQL查询绝大部分知识点,并给出了不同方法及解析,掌握这36道题,SQL查询语句基本上没啥大问题了,上图:

二、学生成绩管理系统数据库设计

1.项目背景及需求分析

1.1 项目背景
1.2 需求分析

2.概念结构设计

2.1 抽象出系统实体
2.2 全局E-R图

3.逻辑结构设计

3.1 关系模式
3.2 函数依赖识别
3.3 范式

4.物理设计和实施

4.1 SQL练习数据库及表创建

MySQL版本:8.0.20

-- 如果已有该数据库,则删除
DROP DATABASE IF EXISTS StudentScore;-- 创建数据库
CREATE DATABASE StudentScore CHARSET=UTF8;-- 使用数据库
USE StudentScore;-- 创建数据表-- table 1: studentsDROP TABLE IF EXISTS students;CREATE TABLE students(
sid INT(20) UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL,
sname VARCHAR(20),
sclass INT(10),
sgender VARCHAR(10),
smajor VARCHAR(20),
sbirthday DATE,
credit_points INT(5) -- 学生已修学分
);-- table 2: teachersDROP TABLE IF EXISTS teachers;CREATE TABLE teachers(
tid INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL,
tname VARCHAR(20),
tschool VARCHAR(20)
);-- table 3: coursesDROP TABLE IF EXISTS courses;CREATE TABLE courses(
cid INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL,
cname VARCHAR(20),
credit_point INT(5), -- 课程学分
tid INT(10) UNSIGNED NOT NULL,
FOREIGN KEY(tid) REFERENCES teachers(tid)
);-- table 4: scoresDROP TABLE IF EXISTS scores;CREATE TABLE scores(
sid INT(10) UNSIGNED NOT NULL,
cid INT(10) UNSIGNED NOT NULL,
score DECIMAL(5, 2),
FOREIGN KEY(sid) REFERENCES students(sid),
FOREIGN KEY(cid) REFERENCES courses(cid)
);

4.2 SQL练习表数据

-- 插入数据INSERT INTO students VALUES
(0, '赵雷', 1, '男', '计算机', '1990-01-01', 3),
(0, '钱电', 2, '男', '计算机', '1990-12-21', 3),
(0, '孙风', 3, '男', '计算机', '1990-12-20', 3),
(0, '李云', 1, '男', '计算机', '1990-12-06', 3),
(0, '周梅', 2, '女', '物理', '1991-12-01', 3),
(0, '吴兰', 3, '女', '物理', '1992-01-01', 3),
(0, '郑竹', 1, '女', '物理', '1989-01-01', 3),
(0, '张三', 2, '女', '物理', '2017-12-20', 3),
(0, '李四', 3, '女', '数学', '2017-12-25', 3),
(0, '李四', 1, '女', '数学', '2012-06-06', 3),
(0, '赵六', 2, '女', '数学', '2013-06-13', 3),
(0, '孙七', 3, '女', '数学', '2014-06-01', 3);INSERT INTO teachers VALUES
(0, '张若尘', '时空学院'),
(0, '孙悟空', '魔法学院'),
(0, '纪梵心', '本源学院'),
(0, '萧炎', '斗气学院'),
(0, '鲁班', '机械学院');INSERT INTO courses VALUES
(0, '变形', 1, 2),
(0, '时空穿梭', 3, 1),
(0, '分解术', 1, 3),
(0, '炼器', 2, 5),
(0, '炼丹', 2, 4),
(0, '飞行', 1, 2);INSERT INTO scores VALUES
(1, 1, 80),
(1, 2, 90),
(1, 3, 99),
(2, 1, 70),
(2, 2, 60),
(2, 3, 80),
(3, 1, 80),
(3, 2, 80),
(3, 3, 80),
(4, 1, 50),
(4, 2, 30),
(4, 3, 20),
(5, 1, 76),
(5, 2, 87),
(6, 1, 31),
(6, 3, 34),
(7, 2, 89),
(8, 1, 88),
(8, 2, 82),
(8, 4, 81),
(9, 6, 95),
(10, 5, 86);

4.3 精选36道SQL查询练习题及答案解析

4.3.1 练习题

4.3.1.1. 连接查询 - 4题

1.1 查询同时选修了课程 1 和 课程 2 的学生的信息

1.2 查询课程 1 比 课程 2 成绩高的学生的信息及课程分数

1.3 查询课程 1 分数小于 60 的学生信息和课程分数,按分数降序排列

1.4 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

4.3.1.2. 子查询、连接查询 - 4题

2.1 查询有成绩的学生信息

2.2 查询学过 孙悟空 老师所授课程的学生信息

2.3 查询至少有一门课与学号为 1 的同学所学相同的学生信息

2.4 查询选修了课程 2 但是没有选修课程 1 的学生信息

4.3.1.3. 聚合分组、连接查询 - 8题

3.1 查询同名学生名单,并统计同名人数

3.2 查询选修了 3 门课程的学生信息

3.3 查询平均成绩大于等于 85 的所有学生的学号、姓名、平均成绩(保留2位小数)

3.4 查询平均成绩大于等于 60 分的学生学号、姓名、平均成绩(保留2位小数)

3.5 查询两门及以上课程分数小于60分的学生学号、姓名及平均成绩(保留2位小数)

3.6 查询姓 赵 的同学的学生信息、总分,若没选课则总分显示为 0

3.7 查询所有同学的学号、姓名、选课总数、总成绩,没选课的学生要求显示选课总数和总成绩为 0

3.8 查询所有学生学号、姓名、选课名称、总成绩,按总成绩降序排序,没选课的学生显示总成绩为 0

4.3.1.4. if 或 case 语句 - 2题

4.1 若学号sid为学生座位编号,现开始对座位号调整,奇数号和偶数号对调,如1和2对调、3和4对调…等, 如果最后一位为奇数,则不调换座位,查询调换后的学生座位号(sid)、姓名,按sid排序

4.2 查询各科成绩最高分、最低分和平均分: 以如下形式显示:课程id、课程名、选修人数、最高分、最低分、平均分、及格率、中等率、优良率、优秀率
及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
要求查询结果按人数降序排列,若人数相同,按课程号升序排列,平均分、及格率等保留2位小数

4.3.1.5. 时间函数 - 6题

5.1 查询 1990 年出生的学生信息

5.2 查询各学生的年龄,分别按年份和按出生日期来算

5.3 查询本周或下周过生日的学生

5.4 查询本月或下月过生日的学生

5.5 查询学生信息,要求:学号和年龄同时至少比一位学生的学号和年龄大

5.6 查询连续相邻3年出生的学生中,学生性别相同的学生信息

4.3.1.6.综合应用 - 12题

6.1 查询和学号为 1 的同学学习的课程完全相同的其他同学的信息

6.2 查询每科均及格的人的平均成绩:学号、姓名、平均成绩(保留2位小数)

6.3 查询选修 张若尘 老师所授课程的学生中,该门课成绩最高的学生信息及成绩(成绩可能重复)

6.4 查询各科成绩,按各科成绩进行排序,并显示排名 分数重复时保留名次空缺,即名次不连续

6.5 查询各科成绩,按各科成绩进行排序,并显示排名 分数重复时不保留名次空缺,即名次连续

6.6 查询学生 赵雷 的 变形 课程成绩的排名:学生信息,分数,排名 分数重复时不保留名次空缺,即名次连续

6.7 查询课程 时空穿梭 成绩在第2-4名的学生,要求显示字段:学号、姓名、课程名、成绩 分数重复时不保留名次空缺,即名次连续

6.8 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺,即名次连续

6.9 查询学生的总成绩,并进行排名,总分重复时保留名次空缺,及名次不连续 排名名次不连续,不需要去重

6.10 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 分别所占百分比 结果:保留2位小数

6.11 查询各科成绩前三名的记录,按照课程编号和分数排序 分数重复时,重复分数按照一名算,即不保留名次空缺,及名次连续

6.12 查询各科成绩的前两名,列出学生信息、课程名、分数,按照课程名、分数排序 分数重复时,重复分数按照一名算,即不保留名次空缺,及名次连续

4.3.2 - 答案及解析

4.3.2.1 连接查询 - 4题


-- 1.1 查询同时选修了课程 1 和 课程 2 的学生的信息select distinct s1.* from students s1 join
scores s2 on s1.sid = s2.sid join
scores s3 on s2.sid = s3.sid and s2.cid=1 and s3.cid;-- 1.2 查询课程 1 比 课程 2 成绩高的学生的信息及课程分数 select * from students s1 join
(select t1.sid, t1.score as course1, t2.score as course2
from scores t1, scores t2
where t1.cid=1 and t2.cid=2 and t1.sid=t2.sid and t1.score > t2.score) as t3
on s1.sid = t3.sid;-- 1.3 查询课程 1 分数小于 60 的学生信息和课程分数,按分数降序排列select s1.*, s2.score from students s1 join
scores s2 on s1.sid = s2.sid and s2.cid = 1 and s2.score < 60
order by s2.score desc;-- 1.4 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩select distinct s1.* from scores s1 join
scores s2 on s1.sid =s2.sid and s1.cid !=s2.cid and s1.score =s2.score;

4.3.2.2 子查询、连接查询 - 4题

-- 2.1 查询有成绩的学生信息-- 连接查询
select distinct s1.* from students s1, scores s2 where s1.sid = s2.sid;select distinct s1.* from students s1 join scores s2 on s1.sid = s2.sid;
-- 子查询
select * from students where sid in (select distinct sid from scores);select * from students where exists (select sid from scores where scores.sid = students.sid);-- 2.2 查询学过 孙悟空 老师所授课程的学生信息-- 连接查询
select s1.* from students s1 join
-- 需要完整代码请添加文章底部微信,付费咨询-- 多级子查询嵌套
select * from students where sid in
-- 需要完整代码请添加文章底部微信,付费咨询-- 2.3 查询至少有一门课与学号为 1 的同学所学相同的学生信息-- 多级子查询嵌套select * from students where sid in
-- 需要完整代码请添加文章底部微信,付费咨询-- 2.4 查询选修了课程 2 但是没有选修课程 1 的学生信息 select s1.* from students s1 join
-- 需要完整代码请添加文章底部微信,付费咨询

4.3.2.3 聚合分组、连接查询 - 8题

-- 3.1 查询同名学生名单,并统计同名人数select sname, count(*) as num from students group by sname having count(*) > 1;-- 3.2 查询选修了 3 门课程的学生信息select * from students
where sid in (select sid from scores group by sid having count(cid) = 3);-- 3.3 查询平均成绩大于等于 85 的所有学生的学号、姓名、平均成绩(保留2位小数)select s2.sid, s1.sname, avg(s2.score) as avgscore from students s1 join
-- 需要完整代码请添加文章底部微信,付费咨询-- 3.4 查询平均成绩大于等于 60 分的学生学号、姓名、平均成绩(保留2位小数)select s1.sid, s1.sname, s2.avgscore from students s1 join
-- 需要完整代码请添加文章底部微信,付费咨询-- 3.5 查询两门及以上课程分数小于60分的学生学号、姓名及平均成绩(保留2位小数)select s1.sid, s1.sname, s2.avgscore from students s1 join
-- 需要完整代码请添加文章底部微信,付费咨询-- 3.6 查询姓 赵 的同学的学生信息、总分,若没选课则总分显示为 0select s1.*, ifnull(s2.total, 0) as total_score from students s1 left join
-- 需要完整代码请添加文章底部微信,付费咨询-- 3.7 查询所有同学的学号、姓名、选课总数、总成绩,没选课的学生要求显示选课总数和总成绩为 0 select s1.sid, s1.sname,
-- 需要完整代码请添加文章底部微信,付费咨询-- 3.8 查询所有学生学号、姓名、选课名称、总成绩,按总成绩降序排序,没选课的学生显示总成绩为 0 select s1.sid, s1.sname, s3.cname,
ifnull(s3.total, 0) as total_score
from students s1 left join
-- 需要完整代码请添加文章底部微信,付费咨询

4.3.2.4 if 或 case 语句 - 2题

-- 4.1 若学号sid为学生座位编号,现开始对座位号调整,奇数号和偶数号对调,如1和2对调、3和4对调...等,
--  如果最后一位为奇数,则不调换座位,查询调换后的学生座位号(sid)、姓名,按sid排序-- 思路:考察对 if 和 case when 的运用,需要关注最后一位是否为奇数,对此进行判断-- if
select if(
sid < (select count(*) from students),
if(sid mod 2 = 0, sid-1, sid+1),
if(sid mod 2 = 0, sid-1, sid)
) as sid, sname from students
order by sid asc;-- case when
select (
case when sid < (select count(*) from students) and sid % 2 != 0 then sid+1
when sid = (select count(*) from students) and sid % 2 != 0 then sid
else sid-1 end
) as sid, sname from students
order by sid asc;-- 4.2 查询各科成绩最高分、最低分和平均分:
--  以如下形式显示:课程id、课程名、选修人数、最高分、最低分、平均分、及格率、中等率、优良率、优秀率
--  及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
--  要求查询结果按人数降序排列,若人数相同,按课程号升序排列,平均分、及格率等保留2位小数-- case when
select s.cid,
c.cname,
-- 需要完整代码请添加文章底部微信,付费咨询-- if
select s.cid, c.cname,
-- 需要完整代码请添加文章底部微信,付费咨询

4.3.2.5 时间函数 - 6题

-- 5.1 查询 1990 年出生的学生信息-- 时间函数:year()
select * from students where year(sbirthday)=1990;-- 5.2 查询各学生的年龄,分别按年份和按出生日期来算-- 按年份算
select sid, sname, (year(curdate()) - year(sbirthday)) as age from students;
-- 按出生日期算select sid, sname, timestampdiff(year, sbirthday, curdate()) as age from students;-- 5.3 查询本周或下周过生日的学生-- 本周
-- 需要完整代码请添加文章底部微信,付费咨询
-- 下周
-- 需要完整代码请添加文章底部微信,付费咨询-- 5.4 查询本月或下月过生日的学生-- 本月
-- 需要完整代码请添加文章底部微信,付费咨询-- 下月
-- 需要完整代码请添加文章底部微信,付费咨询-- 5.5 查询学生信息,要求:学号和年龄同时至少比一位学生的学号和年龄大-- to_days()
-- 需要完整代码请添加文章底部微信,付费咨询-- datediff()
-- 需要完整代码请添加文章底部微信,付费咨询-- 5.6 查询连续相邻3年出生的学生中,学生性别相同的学生信息-- 相邻年份即时间差为1年,通过3表自交对比得出连续3年出生且性别相同的学生,
-- 注意:select 后跟的是哪个表数据,那个表的 sbirthday 就要分别作为连续3年中最小、中间、最大那一年出现select distinct s1.* from students s1 join
students s2 on s1.sgender = s2.sgender join
-- 需要完整代码请添加文章底部微信,付费咨询

4.3.2.6 综合应用 - 12题

-- 6.1 查询和学号为 1 的同学学习的课程完全相同的其他同学的信息--   思路:
--  用 case when 对把其余学生选的课与 1 号学生选的每一门课进行对比,
--  相同就计数 1 ,最后 sum 求和得出其他学生与 1 号学生相同选课数 number,
--  如果 number 与 1 号学生选课数相等,则表示该学生与 1 号同学学习的课程完全相同select * from students
where sid in (select sid from (select s1.sid, sum(case when s2.sid = 1 and s1.cid = s2.cid then 1 else 0 end) as number from scores s1, scores s2 group by sid having s1.sid != 1) s3 where s3.number = (select count(cid) from scores group by sid having sid = 1));-- 6.2 查询每科均及格的人的平均成绩:学号、姓名、平均成绩(保留2位小数)-- 思路:可以先筛选出有不及格科目的学生学号,然后在把这些学生排除掉select s1.sid, s1.sname, s2.avgscore
from students s1,
(select sid, round(avg(score), 2) as avgscore
from scores group by sid) s2
where s1.sid = s2.sid
and s1.sid not in (select distinct sid from scores where score < 60);-- 6.3 查询选修 张若尘 老师所授课程的学生中,该门课成绩最高的学生信息及成绩(成绩可能重复)--     思路:
--  先找出符合条件的课程和分数列表,然后通过分组聚合、聚合函数得到课程编号和最高成绩select s1.*, s2.score from students s1, scores s2
where s1.sid = s2.sid
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.4 查询各科成绩,按各科成绩进行排序,并显示排名
--  分数重复时保留名次空缺,即名次不连续--     思路:
--  1.排名一类的查询一般通过自交(连接)进行对比,通过计算“比当前分数高的分数有几个”来确定排名
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.5 查询各科成绩,按各科成绩进行排序,并显示排名
--  分数重复时不保留名次空缺,即名次连续--     思路:
--  1.通过distinct 去重score,保证排名名次连续;
-- 需要完整代码请添加文章底部微信,付费咨询-- left join
select s1.*, count(distinct s2.score)+1 as '排名' from scores s1
left join scores s2
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.6 查询学生 赵雷 的 变形 课程成绩的排名:学生信息,分数,排名
--  分数重复时不保留名次空缺,即名次连续-- 注意:需要对分数进行去重select s1.*, s2.score,
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.7 查询课程 时空穿梭 成绩在第2-4名的学生,要求显示字段:学号、姓名、课程名、成绩
--  分数重复时不保留名次空缺,即名次连续select s1.sid, s1.sname, c.cname, s2.score
from students s1, scores s2, courses c
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.8 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺,即名次连续--   思路:
--  先分组得出总分,然后通过自交对总分进行比较得出名次,
--  需要注意题目要求总分重复时不保留名次空缺,即需要对自关联的一边去重-- 通过对比
select t1.sid, t1.total, count(t1.total) as '排名' from
(select sid, sum(score) as total from scores group by sid) t1,
-- 需要完整代码请添加文章底部微信,付费咨询-- dense_rank()
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.9 查询学生的总成绩,并进行排名,总分重复时保留名次空缺,及名次不连续
--  排名名次不连续,不需要去重-- 通过对比
select t1.sid, t1.total, count(t1.total) as '排名' from
-- 需要完整代码请添加文章底部微信,付费咨询-- rank()
select *, rank() over (order by total desc) '排名'
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.10 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 分别所占百分比
--  结果:保留2位小数-- 核心思路:分组聚合,用case when, sum, cancat,left join结合使用select c.cname, t.* from courses c
left join (select cid,
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.11 查询各科成绩前三名的记录,按照课程编号和分数排序
--  分数重复时,重复分数按照一名算,即不保留名次空缺,及名次连续
-- 查询结果如下:
-- +-----+-----+-------+
-- | sid | cid | score |
-- +-----+-----+-------+
-- |   8 |   1 | 88.00 |
-- |   1 |   1 | 80.00 |
-- |   3 |   1 | 80.00 |
-- |   5 |   1 | 76.00 |
-- |   1 |   2 | 90.00 |
-- |   7 |   2 | 89.00 |
-- |   5 |   2 | 87.00 |
-- |   1 |   3 | 99.00 |
-- |   2 |   3 | 80.00 |
-- |   3 |   3 | 80.00 |
-- |   6 |   3 | 34.00 |
-- |   8 |   4 | 81.00 |
-- |   9 |   6 | 95.00 |
-- +-----+-----+-------+-- 思路:
-- 这一题逻辑比较简单,但是坑比较多。
-- 核心逻辑是表内分数相互比较得出前3名,需要将单个表定义成2个虚表来实现对比,
-- 关键在于要把重复分数的情况考虑进来,不然容易漏掉
-- 成绩前N名表示比前N名更大的数不会超过N名(去掉重复情况)-- <=
select s1.sid, s1.cid, s1.score
-- 需要完整代码请添加文章底部微信,付费咨询-- <
select * from scores s1
-- 需要完整代码请添加文章底部微信,付费咨询-- 解析:-- 当 where (select count(distinct score) from scores s2 --   where s1.cid = s2.cid and s1.score < s2.score) < 3 在计数时,-- 会把count(distinct score)为 0 的数算进来,所以此时select count(distinct)-- 的结果是[0, 1, 2],即选出s1.score中比s2.score大0个(没有比第1名大的所以为0)、-- 1个(第1名比第2名大所以为1)、2个(第1,2名比第3名大所以为3)的score;-- 图解,以cid=01为例:-- cid   s1.score    s2.score    s2比s1中score大的数有N个(重复不算)-- 01      80           80               0-- 01      80           80               0-- 01      76           76               1-- 01      70           70               2-- 当N=0, 1, 2时,对应s1.score中(80, 80, 76, 70)-- <= 对比时同时取了等号,此时select count(distinct)的结果是[1, 2, 3]select * from scores s1
where (
select count(distinct score) from scores s2
-- 需要完整代码请添加文章底部微信,付费咨询-- 6.12 查询各科成绩的前两名,列出学生信息、课程名、分数,按照课程名、分数排序
--  分数重复时,重复分数按照一名算,即不保留名次空缺,及名次连续select s1.*, c.cname, s2.score
from students s1, scores s2, courses c
where
-- 需要完整代码请添加文章底部微信,付费咨询

4.4 创建一个学生视图,要求显示学生学号、姓名、班级、性别、专业、各科成绩、平均分、总分

DROP VIEW IF EXISTS v_students_info;CREATE VIEW v_students_info AS
SELECT  stu.sid,stu.sname,stu.sclass,stu.sgender,stu.smajor,sum(if(c.cname = "变形", sc.score, 0)) AS "变形",sum(if(c.cname = "时空穿梭", sc.score, 0)) AS "时空穿梭",sum(if(c.cname = "分解术", sc.score, 0)) AS "分解术",sum(if(c.cname = "炼器", sc.score, 0)) AS "炼器",sum(if(c.cname = "炼丹", sc.score, 0)) AS "炼丹",sum(if(c.cname = "飞行", sc.score, 0)) AS "飞行",round(ifnull(avg(sc.score), 0), 2) AS "平均分",ifnull(sum(sc.score), 0) AS "总分"
FROM    students stu LEFT JOINscores sc ON stu.sid = sc.sid LEFT JOINcourses c ON c.cid = sc.cid
GROUP BY stu.sid;

查看视图:

4.5 创建函数

4.5.1 创建一个通过学号sid获取学生信息的函数

DROP FUNCTION IF EXISTS get_student_info_by_sid;DELIMITER //
CREATE DEFINER = CURRENT_USER FUNCTION get_student_info_by_sid(id INT)
RETURNS VARCHAR(300)
-- 需要完整代码请添加文章底部微信,付费咨询
END//
DELIMITER ;
-- 调用函数
SELECT get_student_info_by_sid(8);

调用函数结果:

其中DELIMITER 先定义结束符为 // , 然后又将结束符改为mysql默认的分号结束符。

了解delimiter 关键字请点击:
MySQL中 delimiter 关键字详解
如果出现报错1418:

Error Code : 1418 This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable)

参考下面:
MySQL ERROR 1418 的解决方法

4.5.2 自定义函数 2:要求函数体中包含其中一种流程控制语句,要求输入学生学号sid、课程编号,显示学生姓名、课程名称、成绩是否及格(即成绩>=60)


DROP FUNCTION IF EXISTS get_student_scores_by_id;DELIMITER //
CREATE DEFINER = CURRENT_USER FUNCTION get_student_scores_by_id(sid INT, cid INT)
RETURNS VARCHAR(300)
DETERMINISTIC
BEGIN-- 多个变量要分开声明,否则会报错DECLARE score INT;
-- 需要完整代码请添加文章底部微信,付费咨询END IF;
END//
DELIMITER ;-- 调用函数
SELECT get_student_scores_by_id(1, 2);

调用函数结果:

4.6 创建存储过程

4.6.1 学生每选修一门课,如果该门课程成绩达到60分及以上,则把该门课程学分加到学生学分里面,输出该学生姓名、学分

DROP PROCEDURE IF EXISTS add_scores;DELIMITER //
CREATE DEFINER = CURRENT_USER PROCEDURE add_scores(
-- 需要完整代码请添加文章底部微信,付费咨询
COMMIT;
END//
DELIMITER ;-- 测试调用存储过程
SELECT * FROM students WHERE sid > 10;
CALL add_scores(11, 2, 33, @name, @s_credit_point);
SELECT @name, @s_credit_point;
CALL add_scores(12, 2, 88, @name, @s_credit_point);
SELECT @name, @s_credit_point;

调用存储过程结果:

4.7 创建触发器

4.7.1 创建一个更新学生学分的触发器,如果该学生分数>=60,则给该学生加上这门课的学分

语法
create trigger triggerName
after/before insert/update/delete on 表名 for each row #这句话在mysql是固定的 begin
sql语句;
end;


DROP TRIGGER IF EXISTS update_credit_point;DELIMITER //
CREATE TRIGGER update_credit_point
AFTER INSERT ON scores FOR EACH ROW
-- 需要完整代码请添加文章底部微信,付费咨询END IF;
END//
DELIMITER ;-- 测试数据
SELECT * FROM students WHERE sid < 3;
INSERT INTO scores VALUES
(1, 4, 77),
(2, 4, 55);
SELECT * FROM students;

测试结果:

三、知识点

1. in 和 exists 的用法和区别

mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。

如果查询的两个表大小相当,那么用in和exists差别不大。
如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in。

not in 和not exists: 如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not extsts的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

详情参考:
MySQL中In与Exists的区别
MySQL数据库面试题(2020最新版)

2. rank() 与 dense_rank() 用法

row_number():返回的是行信息,没有排名;
dense_rank():返回的相关名次不会跳跃,名次保持连续;
rank():返回的返回的相关名次会跳跃,名次不连续;

详情参考:
rank()、dense_rank()、row_number() 使用详解

3. 数据库关系代数表达式学习

点击:数据库关系代数表达式学习

精选36道SQL练习题解析 from(原50道SQL练习题)相关推荐

  1. Python学习,我带着练习题来了,50道基础入门练习题(附答案)

    实例001:数字组合 题目 有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析 遍历全部可能,把有重复的剃掉. 1 num=0 2 for a in range ...

  2. mysql经典例题50道52

    mysql经典例题50道52 初学mysql写了50道例题 初学mysql写了50道例题 建表:create table Student(SId varchar(10),Sname varchar(1 ...

  3. 如何快速掌握MYSQL?附牛客网精选的50道SQL题目详解【入门推荐】

    大家早上好,本人姓吴,如果觉得文章写得还行的话也可以叫我吴老师.欢迎大家跟我一起走进数据分析的世界,一起学习! 感兴趣的朋友可以关注我的数据分析专栏,里面有许多优质的文章跟大家分享哦. 另外也欢迎大家 ...

  4. SQL练习题共50道附答案(MySQL)

    点击上方"框架师",选择"置顶公众号" 技术文章第一时间送达! 正文 引言: 最近真的超忙超忙,大家可以根据自己的查询需求更改数据,如果你sql很6那么当然最好 ...

  5. 50道数据库SQL练习题(深入理解各关键字的作用)

    目录 表结构 创建表 练习题 1.查询"001"课程比"002"课程成绩高的所有学生的学号 2.查询所有同学的学号.姓名.选课数.总成绩 3.查询平均成绩大于6 ...

  6. 50道mysql笔试题目及答案_50道SQL练习题及答案与详细分析

    网上流传较广的50道SQL训练,奋斗了不知道多久终于写完了.前18道题的难度依次递增,从19题开始的后半部分算是循环练习和额外function的附加练习,难度恢复到普通状态. 第9题非常难,我反正没有 ...

  7. mysql强化练习_MySQL数据库 - 50道SQL强化练习题

    表和字段: –1.学生表 Student(s_id,s_name,s_birth,s_sex) --学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_i ...

  8. 建议收藏 | 全面解析 50+条 SQL 语句性能优化策略

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 后台回复"k8s",可领取k8s资料 来源:r6d.c ...

  9. 50道MySQL经典练习题

    这个是网上流传的50道SQL练习题,最近拿来练习,刚做完,这里把我做的答案给大家做个参考,如有错误,还请告知. 另外,做题的时候先不要看答案(答案不唯一,只要满足要求即可),要有自己的一个思考过程,这 ...

  10. 50个SQL语句练习题

    50个SQL语句练习题 –1.学生表 Student(SNO,Sname,Sage,Ssex) –SNO 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 –2.课程表 Cour ...

最新文章

  1. POJ 1305 Fermat vs. Pythagoras【勾股数】
  2. 盛大游戏回归A股进入倒计时:估值近300亿 腾讯年初曾入股
  3. linux服务器p2v,使用 Linux dd 命令实现 P2V 或 V2V
  4. vue 时间回显 格式化_VSCode 开发Vue必备插件
  5. 30G 超大数据文件,如何用一周时间导入生产数据库?
  6. bat产品经理能力模型_浅析产品经理能力模型
  7. 谷歌紧急更新,Chrome 今年第二个零日漏洞曝光
  8. Linux中运行c程序,与系统打交道
  9. 深度学习进行语音识别的方法 如何建立自己的语音识别系统
  10. java.text.MessageFormat 专题
  11. linux 汇编 `.eabi_attribute',简单的GBA/NDS汇编程序讲解(ARM汇编)(2008-09-06)
  12. Windows 7 Sp1 x64 安装英文语言包
  13. Kbps、KBps是什么意思?网络下载速度单位换算
  14. Python自学的好方法
  15. 搬了新家,转让一批书。
  16. 【WCN685X】WCN685X hostapd 设置country码不生效问题分析及解决方案
  17. 电脑操作最忌讳18个小动作
  18. JUC之Callable接口
  19. 第十弹:网络公开课,免费学习资源,2020.07.05更新
  20. NVIDIA DLI——深度学习基础-理论与实践入门

热门文章

  1. Tomcat下载安装配置教程
  2. VS2010安装教程
  3. html swf转mp4,《swf转换成mp4及高清视频的方法》.docx
  4. 《Windows游戏编程大师技巧》 四、GDI、控件和突发奇想
  5. qq linux五笔输入法下载官网,【qq五笔官方下载】qq五笔输入法官方下载电脑版 最新版-开心电玩...
  6. 3.30华为笔试第三题
  7. NAT技术与代理服务器的区别
  8. 数学智力题 武士数独题目_数学智力题九宫格
  9. 将连接MySQL数据库的java项目程序打包成为.jar格式
  10. 数据挖掘概念与技术(第三版)课后答案——第一章