建表
课程表:
create table course
(
id int auto_increment
primary key,
name varchar(10) null,
t_id int null
);
教师表:
create table teacher
(
id int auto_increment
primary key,
name varchar(10) null
);
学生表:
create table student
(
id int auto_increment
primary key,
name varchar(10) default '' null,
age datetime null,
sex varchar(10) null
);
成绩表:
create table sc
(
id int auto_increment
primary key,
c_id int null,
s_id int null,
score int null
);
准备数据
课程表:
INSERT INTO course (id, name, t_id) VALUES (1, '语文', 2);
INSERT INTO course (id, name, t_id) VALUES (2, '数学', 1);
INSERT INTO course (id, name, t_id) VALUES (3, '英语', 3);
INSERT INTO course (id, name, t_id) VALUES (4, '体育', 4);
INSERT INTO course (id, name, t_id) VALUES (5, '生物', 5);
INSERT INTO course (id, name, t_id) VALUES (6, '化学', 6);
INSERT INTO course (id, name, t_id) VALUES (7, '物理', 7);
INSERT INTO course (id, name, t_id) VALUES (8, '地理', 7);
教师表:
INSERT INTO teacher (id, name) VALUES (1, '张三');
INSERT INTO teacher (id, name) VALUES (2, '李四');
INSERT INTO teacher (id, name) VALUES (3, '王五');
INSERT INTO teacher (id, name) VALUES (4, '娜美');
INSERT INTO teacher (id, name) VALUES (5, '路飞');
INSERT INTO teacher (id, name) VALUES (6, '王昭君');
INSERT INTO teacher (id, name) VALUES (7, '貂蝉');
学生表:
INSERT INTO student (id, name, age, sex) VALUES (1, '赵磊', '1990-01-01 00:00:00', '男');
INSERT INTO student (id, name, age, sex) VALUES (2, '钱电', '1990-12-21 00:00:00', '男');
INSERT INTO student (id, name, age, sex) VALUES (3, '孙风', '1990-05-20 00:00:00', '男');
INSERT INTO student (id, name, age, sex) VALUES (4, '李云', '1990-08-06 00:00:00', '男');
INSERT INTO student (id, name, age, sex) VALUES (5, '周梅', '1991-12-01 00:00:00', '女');
INSERT INTO student (id, name, age, sex) VALUES (6, '吴兰', '1992-03-01 00:00:00', '女');
INSERT INTO student (id, name, age, sex) VALUES (7, '郑竹', '1989-07-01 00:00:00', '女');
INSERT INTO student (id, name, age, sex) VALUES (8, '王菊', '1990-01-20 00:00:00', '女');
INSERT INTO student (id, name, age, sex) VALUES (9, '王菊', '1990-04-20 00:00:00', '女');
成绩表:
INSERT INTO sc (id, c_id, s_id, score) VALUES (1, 1, 1, 50);
INSERT INTO sc (id, c_id, s_id, score) VALUES (2, 1, 2, 90);
INSERT INTO sc (id, c_id, s_id, score) VALUES (3, 1, 3, 99);
INSERT INTO sc (id, c_id, s_id, score) VALUES (4, 2, 1, 70);
INSERT INTO sc (id, c_id, s_id, score) VALUES (5, 2, 2, 60);
INSERT INTO sc (id, c_id, s_id, score) VALUES (6, 2, 3, 85);
INSERT INTO sc (id, c_id, s_id, score) VALUES (7, 3, 1, 80);
INSERT INTO sc (id, c_id, s_id, score) VALUES (8, 3, 2, 80);
INSERT INTO sc (id, c_id, s_id, score) VALUES (9, 3, 3, 80);
INSERT INTO sc (id, c_id, s_id, score) VALUES (10, 4, 1, 50);
INSERT INTO sc (id, c_id, s_id, score) VALUES (11, 4, 2, 30);
INSERT INTO sc (id, c_id, s_id, score) VALUES (12, 4, 3, 20);
INSERT INTO sc (id, c_id, s_id, score) VALUES (13, 5, 1, 85);
INSERT INTO sc (id, c_id, s_id, score) VALUES (14, 5, 2, 87);
INSERT INTO sc (id, c_id, s_id, score) VALUES (15, 6, 1, 85);
INSERT INTO sc (id, c_id, s_id, score) VALUES (16, 6, 3, 74);
INSERT INTO sc (id, c_id, s_id, score) VALUES (17, 7, 2, 89);
INSERT INTO sc (id, c_id, s_id, score) VALUES (18, 5, 3, 98);
INSERT INTO sc (id, c_id, s_id, score) VALUES (19, 1, 4, 80);
INSERT INTO sc (id, c_id, s_id, score) VALUES (20, 2, 5, 85);
INSERT INTO sc (id, c_id, s_id, score) VALUES (23, 2, 6, 40);
INSERT INTO sc (id, c_id, s_id, score) VALUES (24, 2, 4, 60);
INSERT INTO sc (id, c_id, s_id, score) VALUES (25, 7, 4, 70);
INSERT INTO sc (id, c_id, s_id, score) VALUES (26, 1, 7, 70);
INSERT INTO sc (id, c_id, s_id, score) VALUES (27, 2, 7, 70);
INSERT INTO sc (id, c_id, s_id, score) VALUES (28, 3, 7, 70);
INSERT INTO sc (id, c_id, s_id, score) VALUES (29, 7, 1, 70);
INSERT INTO sc (id, c_id, s_id, score) VALUES (30, 8, 1, 70);
题目练习(sql是自己写的,有自测过)
- 查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数
select s.id, s.name, s2.score, s3.score
from student as s
join sc as s2 on s.id = s2.s_id and s2.c_id = 1
left join sc as s3 on s.id = s3.s_id and s3.c_id = 2
where if(s3.id is null, True, s2.score > s3.score)
group by s.id;
- 查询同时存在" 01 "课程和" 02 "课程的情况
select s.name, s2.c_id, s3.c_id
from student as s
join sc as s2 on s.id = s2.s_id and s2.c_id = 1
join sc as s3 on s.id = s3.s_id and s3.c_id = 2;
- 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )
select s.name, s2.c_id, s3.c_id
from student as s
join sc as s2 on s.id = s2.s_id and s2.c_id = 1
left join sc as s3 on s.id = s3.s_id and s3.c_id = 2;
- 查询不存在" 01 "课程但存在" 02 "课程的情况
select s.name, s2.c_id, s3.c_id
from student as s
left join sc as s2 on s.id = s2.s_id and s2.c_id = 1
join sc as s3 on s.id = s3.s_id and s3.c_id = 2
where s2.id is null;
- 查询在 SC 表存在成绩的学生信息
select s.*
from student as s
left join sc as s2 on s.id = s2.s_id
where s2.id is not null
group by s.id;
- 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
select s.id, s.name, count(s2.c_id), sum(s2.score)
from student as s
left join sc as s2 on s.id = s2.s_id
group by s.id;
- 查询「李」姓老师的数量
select count(1) from teacher where name like '李%';
- 查询学过「张三」老师授课的同学的信息
select s2.*
from teacher as t
join course as c on t.id = c.t_id
join sc as s on s.c_id = c.id
join student as s2 on s.s_id = s2.id
where t.name = '张三';
- 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
select s2.id, s2.name, avg(s.score) as score
from sc as s
join student as s2 on s.s_id = s2.id
group by s2.id
having score >= 60;
- 查询没有学全所有课程的同学的信息
select s.*
from student as s
join sc as s2 on s.id = s2.s_id
group by s.id
having count(s2.c_id) < (select count(1) from course);
- 查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
select *
from student
where id in (select s_id from sc where c_id in (select c_id from sc where s_id = 1))
and id != 1;
- 查询包含" 01 "号的同学学习的所有课程的其他同学的信息
select *
from student as s
where s.id in (select s2.s_id
from sc as s2
where s2.c_id in (select s3.c_id from sc as s3 where s3.s_id = 1)
and s2.s_id != 1
group by s2.s_id
having count(distinct s2.c_id) = (select count(1) from sc where s_id = 1));
select *
from student as s
join sc as s2 on s.id = s2.s_id
where s2.c_id in (select s3.c_id from sc as s3 where s3.s_id = 1)
and s2.s_id != 1
group by s2.s_id
having count(distinct s2.c_id) = (select count(1) from sc where s_id = 1);
12.1 查询和" 01 "号的同学学习的课程完全相同的其他同学的信息
select *
from student as s
where s.id in (select s2.s_id
from sc as s2
where s2.c_id in (select s3.c_id from sc as s3 where s3.s_id = 1)
and s2.s_id != 1
group by s2.s_id
having count(distinct s2.c_id) = (select count(1) from sc where s_id = 1)
and (select count(1) from sc where s_id = s2.s_id) = (select count(1) from sc where s_id = 1));
- 查询没学过"张三"老师讲授的任一门课程的学生姓名
select distinct s.*
from student as s
left join sc as s2 on s.id = s2.s_id
where s2.id is null
or (s2.s_id not in (select s3.s_id
from course as c
join teacher as t on c.t_id = t.id and t.name = '张三'
join sc as s3 on s3.c_id = c.id));
- 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
select s.*, avg(s4.score)
from student as s
join sc as s2 on s.id = s2.s_id
join sc as s3 on s.id = s3.s_id and s2.id != s3.id
join sc as s4 on s.id = s4.s_id
where s2.score < 60
and s3.score < 60
group by s.id;
select s.*, avg(s3.score)
from student as s
join sc as s2 on s.id = s2.s_id and s2.score < 60
join sc as s3 on s.id = s3.s_id
group by s.id
having count(distinct s2.id) >= 2;
- 检索" 01 "课程分数小于 60,按分数降序排列的学生信息
select s.*
from student as s
join sc as s2 on s.id = s2.s_id
where s2.c_id = 1
and s2.score < 60
order by s2.score desc;
- 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
select s.*, tmp.avg_score
from sc as s
join (
select s2.s_id, avg(s2.score) as avg_score from sc as s2 group by s2.s_id
) as tmp on s.s_id = tmp.s_id
order by tmp.avg_score desc;
- 查询各科成绩最高分、最低分和平均分: 以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select c_id,
c.name,
count(s_id) as 'member',
max(score) as 'max_score',
min(sc.score) as 'min_score',
avg(sc.score) as 'avg_score',
sum(case when sc.score>=60 then 1 else 0 end)/count(1) as '及格率',
sum(case when sc.score>=70 and sc.score < 80 then 1 else 0 end)/count(1) as '中等率',
sum(case when sc.score>=80 and sc.score< 90 then 1 else 0 end)/count(1) as '优良率',
sum(case when sc.score>=90 then 1 else 0 end)/count(1) as '优秀率'
from sc
join course as c on sc.c_id = c.id
group by sc.c_id
order by count(sc.s_id) desc, sc.c_id;
- 按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺
select s.*,
count(s2.score) + 1 as r
from sc as s
left join sc as s2 on s.c_id = s2.c_id and s.score < s2.score
group by s.c_id, s.s_id
order by s.c_id, r;
- 按各科成绩进行排序,并显示排名, Score 重复时合并名次
select s.*,
count(distinct s2.score) + 1 as r
from sc as s
left join sc as s2 on s.c_id = s2.c_id and s.score < s2.score
group by s.c_id, s.s_id
order by s.c_id, r;
- 查询学生的总成绩,并进行排名,总分重复时保留名次空缺
select tmp.s_id, count(tmp2.score) + 1 r
from (select s_id, sum(score) score from sc group by s_id) as tmp
left join (select s_id, sum(score) score from sc group by s_id) as tmp2
on tmp.s_id != tmp2.s_id and tmp.score < tmp2.score
group by tmp.s_id
order by r, tmp.s_id;
- 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
select tmp.s_id, tmp.score, count(distinct tmp2.score) + 1 r
from (select s_id, sum(score) score from sc group by s_id) as tmp
left join (select s_id, sum(score) score from sc group by s_id) as tmp2
on tmp.s_id != tmp2.s_id and tmp.score < tmp2.score
group by tmp.s_id
order by r, tmp.s_id;
- 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
select s.c_id,
count(s.s_id) as totalnum,
tmp.num as num_85_100,
tmp1.num as num_85_70,
tmp2.num as num_60_70,
tmp3.num as num_0_60,
ifnull(tmp.num/count(s.s_id), 0) '[100-85]',
ifnull(tmp1.num/count(s.s_id), 0) '[85-70]',
ifnull(tmp2.num/count(s.s_id), 0) '[70-60]',
ifnull(tmp3.num/count(s.s_id), 0) '[60-0]'
from sc as s
left join (select s2.c_id, count(s2.s_id) num from sc as s2 where s2.score>= 85 group by s2.c_id) tmp on tmp.c_id = s.c_id
left join (select s3.c_id, count(s3.s_id) num from sc as s3 where s3.score< 85 and s3.score >=70 group by s3.c_id) tmp1 on tmp1.c_id = s.c_id
left join (select s4.c_id, count(s4.s_id) num from sc as s4 where s4.score>= 60 and s4.score < 70 group by s4.c_id) tmp2 on tmp2.c_id = s.c_id
left join (select s5.c_id, count(s5.s_id) num from sc as s5 where s5.score< 60 group by s5.c_id) tmp3 on tmp3.c_id = s.c_id
group by s.c_id
order by s.c_id;
select c_id,
sum(case when score<60 then 1 else 0 end)/count(1) as '[60-0]',
sum(case when score>=60 and score<70 then 1 else 0 end)/count(1) as '[70-60]',
sum(case when score>=70 and score<85 then 1 else 0 end)/count(1) as '[85-70]',
sum(case when score>=85 then 1 else 0 end)/count(1) as '[100-85]'
from sc
group by c_id
order by c_id;
- 查询各科成绩前三名的记录
select s.c_id, s.s_id, s.score
from sc as s
left join sc as s2 on s.c_id = s2.c_id and s.score < s2.score
group by s.c_id, s.s_id
having count(s2.score) < 3
order by s.c_id, s.score desc;
- 查询每门课程被选修的学生数
select c_id, count(s_id)
from sc
group by c_id;
- 查询出只选修两门课程的学生学号和姓名
select s.id, s.name
from student as s
join sc as s2 on s.id = s2.s_id
group by s.id
having count(s2.c_id) = 2;
- 查询男生、女生人数
select sex, count(1)
from student
group by sex;
- 查询名字中含有「风」字的学生信息
select *
from student
where name like '%风%';
- 查询同名同性学生名单,并统计同名人数
select name, count(1)
from student
group by name, sex
having count(1) > 1;
- 查询 1990 年出生的学生名单
select *
from student
where year(age) = '1990';
- 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select c.name, avg(s.score) as 'avg_score'
from course as c
left join sc as s on c.id = s.c_id
group by c.id
order by avg_score desc, c.id asc;
- 查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
select s.id, s.name, avg(s2.score)
from student as s
join sc as s2 on s.id = s2.s_id
group by s.id
having avg(s2.score) >= 85;
- 查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
select s.id, s.name, s2.score
from student as s
join sc as s2 on s.id = s2.s_id
join course as c on s2.c_id = c.id
where c.name = '数学'
and s2.score < 60;
- 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
select s.id, s.name, c.name, s2.score
from student as s
left join sc as s2 on s.id = s2.s_id
left join course as c on c.id = s2.c_id
order by s.id, s2.c_id;
- 查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
select s.name, c.name, s2.score
from student as s
join sc as s2 on s.id = s2.s_id
join course as c on s2.c_id = c.id
where s2.score > 70;
- 查询不及格的课程
select *
from sc
where score < 60;
- 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
select s.id, s.name, s2.score
from student as s
join sc as s2 on s.id = s2.s_id
where s2.c_id = 1
and s2.score > 80;
- 求每门课程的学生人数
select c.id, c.name, ifnull(count(s.s_id), 0) as 'total'
from course as c
left join sc as s on c.id = s.c_id
group by c.id;
- 成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select s.*, s2.score
from student as s
join sc as s2 on s.id = s2.s_id
join course as c on s2.c_id = c.id
join teacher as t on c.t_id = t.id
where t.name = '张三'
order by s2.score desc
limit 1;
- 成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select s.*, s2.score, s2.c_id
from student as s
join sc as s2 on s.id = s2.s_id
join
(
select c.id as course_id, max(s.score) as max_score
from teacher as t
join course as c
on t.id = c.t_id
join sc as s on c.id = s.c_id
where t.name = '张三'
group by t.id
) as tmp on s2.c_id = tmp.course_id and s2.score = tmp.max_score;
- 查询不同课程成绩都相同的学生的学生编号、课程编号、学生成绩
select *
from sc
where s_id in (select s_id from sc group by s_id having max(score) = min(score));
select C.s_id, max(C.c_id) c_id, max(C.score) score
from sc C
left join(select s_id, avg(score) A from sc group by s_id) B
on C.s_id = B.s_id
where C.score = B.A
group by C.s_id
having COUNT(0) = (select COUNT(0) from sc where s_id = C.s_id);
- 查询每门课程成绩最好的前两名
select s.c_id, s.s_id, s.score
from sc as s
left join sc as s2 on s.c_id = s2.c_id and s.score < s2.score
group by s.c_id, s.s_id
having count(s2.score) < 2
order by s.c_id, s.score desc;
- 统计每门课程的学生选修人数(超过 5 人的课程才统计)
select c.*
from course as c
join sc as s on c.id = s.c_id
group by c.id
having count(s.s_id) > 5;
- 检索至少选修两门课程的学生学号
select s_id
from sc
group by s_id
having count(c_id) >= 2;
- 查询选修了全部课程的学生信息
select s.s_id
from sc as s
group by s.s_id
having count(s.c_id) = (select count(1) from course);
- 查询各学生的年龄,只按年份来算
select id, name, year(age)
from student;
- 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
select id,
name,
if(month(age) > month(now()) or (month(age) = month(now()) and day(age) > day(now())), age,
date_sub(age, interval 1 year)) as new_age
from student;