精选36道SQL练习题解析 from(原50道SQL练习题)

2023-11-09

SQL练习题

友情链接

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: students

DROP 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: teachers

DROP 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: courses

DROP 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: scores

DROP 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 查询姓 赵 的同学的学生信息、总分,若没选课则总分显示为 0

select 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 JOIN
		scores sc ON stu.sid = sc.sid LEFT JOIN
		courses 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. 数据库关系代数表达式学习

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

精选36道SQL练习题解析 from(原50道SQL练习题) 的相关文章

  • 处理大数据表时应该如何使用Hibernate Mapping

    问题定义 我有一个包含大量数据 超过 100 000 行 的数据库表 表结构如下 AppID DocID DocStatus 1 100 0 1 101 1 2 200 0 2 300 1 每个 applicationID 可能有数千个文档
  • SQL Server 2008 GUID 列全为 0

    我希望这是我做的一个简单的傻事 我的数据库中有一个表 设置如下 column name widget guid data type uniqueidentifier allow nulls false default value newid
  • 如何在php/mysql中使用事务

    我正在使用 php mysql 我知道 mysql 中的事务 但不能在我的脚本中使用 下面是我的脚本 如何在我的代码中使用 php 事务 即 BEGIN ROLLBACK COMMIT foreach json a shop as json
  • 如何使用Python3.4在tornado中进行异步mysql操作?

    我现在使用Python3 4 我想在Tornado中使用异步mysql客户端 我已经发现torndb https github com bdarnell torndb但在阅读其源代码后 我认为它无法进行异步mysql操作 因为它只是封装了M
  • 如何插入包含“&”的字符串

    如何编写包含 字符的插入语句 例如 如果我想将 J J Construction 插入数据库的列中 我不确定这是否有什么不同 但我正在使用 Oracle 9i 我总是忘记这一点 然后又回到它 我认为最好的答案是迄今为止提供的答复的组合 首先
  • 火鸟删除速度很慢

    我正在做这个简单的交易 DELETE FROM ominve01 WHERE CVE OBS IN SELECT CVE OBS FROM minve01 M WHERE M FECHA DOCU lt 31 12 2010 OR FECH
  • 将自动递增值添加到只有一列的表中

    我需要创建一个基本上仅保留索引列表的表 因此 我创建了一个只有一个名为 id 的自动递增列的表 但是 我似乎无法隐式地将自动递增值添加到该表中 我知道通常当您在表中有这样一列 不仅仅是此列 时 您可以执行以下操作 插入表 col1 col2
  • 在 SQL 中如何获得整数的最大值?

    我试图从 MySQL 数据库中找出整数 有符号或无符号 的最大值 有没有办法从数据库本身提取这些信息 是否有我可以使用的内置常量或函数 标准 SQL 或 MySQL 特定的 At http dev mysql com doc refman
  • “create_date”时间戳字段的默认值无效

    我有以下 sql 创建语句 mysql gt CREATE TABLE IF NOT EXISTS erp je menus gt id INT 11 NOT NULL AUTO INCREMENT gt name VARCHAR 100
  • 更高效的 LINQ 查询

    有人可以帮我将此查询循环变成高效的 Linq 查询吗 我将其加载到 TreeView 中 因此必须附加每个项目 包含也非常低效 延迟加载项目也不起作用 事实上 这个查询访问数据库的次数比应有的要多 public IQueryable
  • SQLite 使用循环重新编号 ID

    您好 我有一个包含许多插入行的表 我需要按 id 对所有行重新编号并排序 我找到了这段代码 但它对我不起作用 SET i 100 UPDATE main Categories SET ID i i 1 WHERE Name White AL
  • 转义用户数据,无需魔法引号

    我正在研究如何在来自外部世界的数据被用于应用程序控制 存储 逻辑等之前正确地对其进行转义 显然 随着 magic quote 指令在 php 5 3 0 中很快被弃用 并在 php6 中被删除 对于任何想要升级并进入新语言功能 同时维护遗留
  • 从一张表更新并插入另一张表

    我有两张桌子 table1 ID 代码 姓名 table2 ID 代码 姓名 具有相同的列 我想将数据从 table1 插入到 table2 或更新列 如果 table2 中存在 table1 ID table2 ID 执行此操作的简单方法
  • PostgreSQL WHERE 计数条件

    我在 PostgreSQL 中有以下查询 SELECT COUNT a log id AS overall count FROM Log as a License as b WHERE a license id 7 AND a licens
  • 将非常大的Python列表输出保存到mysql表中

    我想将 python 生成的列表的输出保存在 mysql 数据库的表中 该表如下所示 mysql 中的 myapc8 表 https i stack imgur com 4B4Hz png这是Python代码 在此输入图像描述 https
  • Monkeyrunner/jython 中未找到 JDBC 驱动程序错误

    我需要在中插入一些东西DB 我在用着JDBC as a connector jython the script mysql数据库和脚本正在运行CentOS 我的代码看起来像这样 from com android monkeyrunner i
  • MySQL 两种日期格式之间的转换

    用户将以这种格式输入日期 2017 年 2 月 17 日 存储在 mysql 数据库中的日期格式如下 2015 02 17 00 00 00 我想做的是 SELECT FROM insurance where DATE FORMAT in
  • 控制数据是否存在于数组中

    我在mysql中有两个不同的表 我正在使用curl从json文件中获取数据 我的第一个表名称是 tblclients 该表存储客户端数据 我的第二个表名称是 tblcustomfieldsvalues 该表使用 tblclients 表的
  • 在 Oracle 中如何将多行组合成逗号分隔的列表? [复制]

    这个问题在这里已经有答案了 我有一个简单的查询 select from countries 结果如下 country name Albania Andorra Antigua 我想在一行中返回结果 如下所示 Albania Andorra
  • 如何关闭整个数据库的区分大小写

    我创建了一个包含许多脚本和许多存储过程的数据库 在这个数据库中 我们没有注意担心区分大小写 因为它对于我的本地开发计算机来说是关闭的 综上所述 我试图弄清楚如何使以下两条语句返回相同的结果 SELECT FROM companies SEL

随机推荐

  • 怎样改变input被选中时边框颜色

    1 当input获得焦点时 input focus outline 1px solid 000 2 输入合法时 input valid border 1px solid green 3 输入不合法时 input invalid border
  • ElasticSearch 入门教程笔记

    视频教程 狂神说Java ElasticSearch7 6 x最新完整教程通俗易懂 视频地址 https www bilibili com video BV17a4y1x7zq 拒绝白嫖 感谢狂神分享的视频教程 ElasticSearch
  • Echarts 给pie圆饼图series.data 赋值

    1 如何去掉字符串最外层的双引号 使其变成数组 var data id 32 wd 20 3 jd 113 3 id 321 wd 20 3 jd 113 3 var yy var mm yy data split for var i 0
  • 数据挖掘算法与现实生活中的应用案例

    如何分辨出垃圾邮件 如何判断一笔交易是否属于欺诈 如何判断红酒的品质和档次 扫描王是如何做到文字识别的 如何判断佚名的著作是否出自某位名家之手 如何判断一个细胞是否属于肿瘤细胞 等等 这些问题似乎都很专业 都不太好回答 但是 如果了解一点点
  • 归因分析计算因子贡献度常见的方法

    在归因分析中 我们一般都需要计算出每个因子的贡献度是多少 比如产品DAU上升 对年龄段维度进行拆解 看是不同年龄段的用户对DAU上升的贡献度是多少 一般根据指标的类型 计算贡献度的方法也不一样 下面就列出一些常见的归因分析贡献度的计算方法
  • mt4服务器显示无连接,MT4登录显示“无效账户”,“无法连接”怎么解决

    MT4账户分为实盘账户和模拟账户 小编每天都会收到很多客户实盘账号登入不上去的申请 有的客户反应账户显示登录无效 或者无连接 没有数据流 客户就会问 是不是我的账号过期不能使用 其实不是的 账户登入不上有如下几个原因 首先我先要告诉大家 一
  • ISP(图像信号处理)算法概述、工作原理、架构、处理流程

    转自 https zhuanlan zhihu com p 115321553 ISP的主要内部构成 ISP内部包含 CPU SUP IP 各种功能模块的通称 IF 等设备 ISP的控制结构 1 ISP逻辑 2 运行在其上的firmware
  • ARM 浮点运算详解

    一 早期ARM上的浮点模拟器 早期的ARM没有协处理器 所以浮点运算是由CPU来模拟的 即所需浮点运算均在浮点运算模拟器 float math emulation 上进行 需要的浮点运算 常要耗费数千个循环才能执行完毕 因此特别缓慢 直到今
  • Vue路由中,history和hash两种模式有什么区别?

    前端路由有两种模式 hash 模式和 history 模式 接下来分析这两种模式的实现方式和优缺点 hash 模式 hash 模式是一种把前端路由的路径用井号 拼接在真实 URL 后面的模式 当井号 后面的路径发生变化时 浏览器并不会重新发
  • MySQL 表连接 JOIN

    参考 表连接 前言 建表语句 测试数据 一 表连接JOIN基础 1 什么是表连接 什么是JOIN 2 表连接的分类 2 1 内连接 2 2 外连接 2 3 等值连接 2 4 自然连接 前言 建表语句 表a CREATE TABLE a ta
  • C++迭代器作为参数传递进函数使用时的注意事项

    外部函数对迭代器进行值传递而非引用 需要注意的一点是在使用迭代器作为传入参数进行迭代器运算操作的时候 作用对象仅仅是对传入迭代器的拷贝 因为在传入迭代器后函数直接对传入的对象进行拷贝操作而不访问源对象的内存空间https blog csdn
  • html 线条外阴影,怎么添加阴影边框?

    本文介绍使用CSS添加阴影边框和word文档中添加阴影边框的方法 有一定的参考价值 有需要的朋友可以参考一下 希望对大家有所帮助 CSS添加阴影边框的方法 方法1 使用box shadow属性添加阴影边框 相关推荐 css在线手册 box
  • 程序员最全的Linux命令,不全来找我随时更新!

    一 引言 1 1 Linux引言 Linux是一套免费使用和自由传播的类Unix操作系统 是一个基于POSIX和Unix的多用户 多任务 支持多线程和多CPU的操作系统 伴随着互联网的发展 Linux得到了来自全世界软件爱好者 组织 公司的
  • 常见传感器和芯片的介绍

    文章目录 一 传感器 1 1 KY xxxx系列 KY 002 KY 003 KY 004 KY 005 KY 006 KY 007 KY 008 KY 009 KY 010 KY 011 KY 012 KY 013 KY 014 KY 0
  • 虚拟服务器ftp上传权限设置,13. 为 FTP虚拟用户设置“不同文件目录”和“访问权限”...

    Re FTP 文件传输服务 FTP 服务不论在企业或教学中 是很常用的文件共享方式 它既可以做到匿名访问 也可以做到用户名和密码访问 更可以做到只能提交但不能够访问的特殊要求等等功能 本课程将一一详细演示 FTP 服务器的一般应用场景在 企
  • check allInputDimensionsSpecified() for second profile fail

    目录 yolov7 tensorrt预测时报错 在python代码里 在调用engine推理前做这样的设置即可 yolov7修改后的tenorr
  • Java JUC概述

    Java JUC Java Util Concurrent 是 Java 平台提供的并发编程工具包 它提供了一系列的工具类和接口 用于简化多线程编程 JUC 中的类和接口都是基于 Java 平台的底层并发原语 如锁 信号量 原子变量等 实现
  • 机器视觉及其应用发展

    导读 一 机器视觉的研究和发展动态 机器视觉的研究 发展和应用还远没有达到成熟的程度 机器视觉从诞生到今天才只有短短的三十多年时间 在机器视觉中承担 大脑 作用的图像分析处理 图像理解和模式识别理论和技术基础还非常不完善 甚至 机器视觉的图
  • TextMeshPro 使用及性能

    目录 TextMeshPro 组件介绍 Main Setting Extra Setting 轮廓 阴影 外发光 表情混编使用 表情资源制作 中文字体制作 关于性能 TextMeshPro ps 第一次写博客 排版和表述可能有不尽人意的地方
  • 精选36道SQL练习题解析 from(原50道SQL练习题)

    SQL练习题 友情链接 1 医疗信息管理系统数据库 MySQL 2 邮件管理数据库设计 MySQL 3 SQL Server医疗信息管理系统数据库 英文版 源码 Medical Management System Database 4 SQ