MySQL经典50题的习题及参考答案
练习数据
数据表
--1.学生表 Student(s_id,s_name,s_age,s_sex)
--s_id学生编号,s_name学生姓名,s_age出生年月,s_sex学生性别
--2.课程表 Course(c_id,c_name,t_id) --c_id--课程编号,c_name课程名称,t_id 教师编号
--3.教师表 Teacher(t_id ,t_name) --t_id教师编号,t_name 教师姓名
--4.成绩表 SC(s_id,c_id,s_score) --s_id学生编号,c_id课程编号,s_score分数
建表插入数据
--建表
--学生表
CREATE TABLE `Student`(
`s_id` VARCHAR(20),
`s_name` VARCHAR(20) NOT NULL DEFAULT '',
`s_birth` VARCHAR(20) NOT NULL DEFAULT '',
`s_sex` VARCHAR(10) NOT NULL DEFAULT '',
PRIMARY KEY(`s_id`)
);
--课程表
CREATE TABLE `Course`(
`c_id` VARCHAR(20),
`c_name` VARCHAR(20) NOT NULL DEFAULT '',
`t_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`c_id`)
);
--教师表
CREATE TABLE `Teacher`(
`t_id` VARCHAR(20),
`t_name` VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY(`t_id`)
);
--成绩表
CREATE TABLE `Score`(
`s_id` VARCHAR(20),
`c_id` VARCHAR(20),
`s_score` INT(3),
PRIMARY KEY(`s_id`,`c_id`)
);
--插入学生表测试数据
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-05-20' , '男');
insert into Student values('04' , '李云' , '1990-08-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-03-01' , '女');
insert into Student values('07' , '郑竹' , '1989-07-01' , '女');
insert into Student values('08' , '王菊' , '1990-01-20' , '女');
--课程表测试数据
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');
--教师表测试数据
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
--成绩表测试数据
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);
练习题目及答案
题目1:查询"01"课程比"02"课程成绩高的学生的信息及课程分数
SQL实现
-- 方法1
SELECT
st.*,
sc1.s_score "01_score",
sc2.s_score "02_score"
FROM
Student st -- 两个表通过学号连接,指定01
LEFT JOIN Score sc1 ON st.s_id = sc1.s_id
AND sc1.c_id = "01" -- 两个表通过学号连接,指定02
LEFT JOIN Score sc2 ON st.s_id = sc2.s_id
AND sc2.c_id = "02"
WHERE
sc1.s_score > sc2.s_score -- 判断条件
-- 方法2:直接使用where语句
SELECT
st.*,
s1.s_score "01_score",
s2.s_score "02_score"
FROM
Student st,
Score s1,
Score s2
WHERE -- 列出全部的条件
st.s_id = s1.s_id
AND st.s_id = s2.s_id
AND s1.c_id = "01"
AND s2.c_id = "02"
AND s1.s_score > s2.s_score -- 01成绩高
方法1结果:
方法2结果:
题目2:查询"01"课程比"02"课程成绩低的学生的信息及课程分数(题目1是成绩高)
SQL实现
类似于题目1,将大于改为小于(偷个懒,不贴代码了!)
题目3:查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
SQL实现
-- 执行顺序:先执行分组,再执行avg平均操作
SELECT
st.s_id,
st.s_name,
ROUND(( sc.s_score ),2) avg_score
FROM
Student st
LEFT JOIN Score sc
ON st.s_id=sc.s_id
GROUP BY
sc.s_id
HAVING
AVG( sc.s_score ) >= 60
结果如下:
题目4:查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩(包括有成绩的和无成绩的)
SQL实现
-- 方法1:使用case when语句
SELECT
st.s_id,
st.s_name,
( CASE WHEN AVG( sc.s_score ) IS NULL THEN 0 ELSE ROUND(( sc.s_score ),2) END ) avg_score
FROM
Student st
LEFT JOIN Score sc ON st.s_id = sc.s_id
GROUP BY
sc.s_id
HAVING
AVG( sc.s_score ) < 60
OR AVG( sc.s_score ) IS NULL
-- 方法2:使用ifnull函数
SELECT
st.s_id,
st.s_name,
ROUND( avg( ifnull( sc.s_score, 0 ) ), 2 ) AS avg_score
FROM
Student st
LEFT JOIN Score sc ON st.s_id = sc.s_id
GROUP BY sc.s_id
HAVING avg_score < 60
方法1结果:
方法2结果:
题目5:查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
SQL实现
SELECT
st.s_id,
st.s_name,
COUNT(sc.c_id) course_number,
SUM(sc.s_score) score_sum
FROM
Student st
LEFT JOIN
Score sc
ON st.s_id = sc.s_id
GROUP BY st.s_id
结果如下:
题目6:查询“李”姓老师的数量
SQL实现
SELECT
t.t_name,
COUNT( t.t_name ) name_li_number
FROM
Teacher t
WHERE
t_name LIKE "李%"
结果如下:
题目7:查询学过张三老师授课的同学的信息
SQL实现
I-- 比较简单的方法
SELECT
st.*
FROM
Student st,
Course c,
Score sc,
Teacher t
WHERE
st.s_id = sc.s_id
AND sc.c_id = c.c_id
AND c.t_id = t.t_id
AND t.t_name = "张三"
-- 使用id查询
SELECT
st.*
FROM
Student st
WHERE
st.s_id IN (
SELECT
s_id -- 2.通过课程找出对应的学号
FROM
Score S
JOIN Course C ON S.c_id = C.c_id -- 课程表和成绩表
WHERE
C.t_id IN ( SELECT t_id FROM Teacher WHERE t_name = "张三" )
)
方法1结果:
方法2结果:
题目8:找出没有学过张三老师课程的学生
SQL实现
使用题目7方法2中没在张三老师教课内容的学生,代码如下:
SELECT
st.*
FROM
Student st
WHERE
st.s_id not IN (
SELECT
s_id -- 2.通过课程找出对应的学号
FROM
Score S
JOIN Course C ON S.c_id = C.c_id -- 课程表和成绩表
WHERE
C.t_id IN ( SELECT t_id FROM Teacher WHERE t_name = "张三" )
)
结果如下:
题目9:查询学过编号为01,并且学过编号为02课程的学生信息
SQL实现
-- in方法实现
SELECT
st.*
FROM
Student st
WHERE
st.s_id IN (
SELECT
s1.s_id
FROM
Score s1
JOIN Score s2 ON s1.s_id = s2.s_id
WHERE
s1.c_id = "01"
AND s2.c_id = "02"
)
-- 普通方法
SELECT
st.*
FROM
Student st,
Score s1,
Score s2
WHERE
st.s_id = s1.s_id
AND s1.s_id = s2.s_id
AND s1.c_id = "01"
AND s2.c_id = "02"
方法1结果:
方法2如下:
题目10:查询学过01课程,但是没有学过02课程的学生信息(注意和上面 题目的区别)
SQL实现
-- 方法1
SELECT
st.*
FROM
Student st
WHERE st.s_id in (SELECT s_id FROM Score WHERE c_id="01")
AND st.s_id not in (SELECT s_id FROM Score WHERE c_id="02")
-- 方法2
SELECT
st.*
FROM
Student st
WHERE
st.s_id IN ( SELECT s_id FROM Score s1 WHERE s1.c_id = "01" AND s_id NOT IN ( SELECT s_id FROM Score WHERE c_id = "02" ) )
方法1结果:
方法2结果:
题目11:查询没有学完全部课程的同学的信息
SQL实现
SELECT
st.*
FROM
Student st
WHERE
st.s_id NOT IN (
SELECT s_id FROM Score GROUP BY s_id HAVING COUNT( s_id ) = ( SELECT COUNT( * ) FROM Course )
)
结果如下:
题目12:查询至少有一门课与学号为01的同学所学相同的同学的信息
SQL实现
-- 方法1
SELECT
*
FROM
Student st
WHERE
s_id IN (
SELECT DISTINCT s_id FROM Score WHERE c_id IN
( SELECT c_id FROM Score WHERE s_id = "01" )
) AND s_id <> "01"
-- 方法2
SELECT
st.*
FROM
Student st
JOIN Score s2 ON st.s_id = s2.s_id
AND c_id IN ( SELECT c_id FROM Score WHERE s_id = '01' )
GROUP BY
st.s_id
HAVING
st.s_id <> "01"
方法1结果:
方法2结果:
题目13:查询和01同学学习的课程完全相同的同学的信息
SQL实现
SELECT
st.*
FROM
Student st
WHERE
st.s_id IN (
SELECT
s_id
FROM
Score
GROUP BY
s_id
HAVING
GROUP_CONCAT( c_id ORDER BY c_id ) = ( SELECT GROUP_CONCAT( c_id ORDER BY c_id ) FROM Score GROUP BY s_id HAVING s_id = "01" )
AND s_id <> "01"
)
结果如下:
说明:本题中使用了group_concat函数,其具体的使用方法为:group_concat([DISTINCT] 字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
案例:
SELECT s_id,GROUP_CONCAT(c_id ORDER BY c_id) FROM Score GROUP BY s_id
结果如下:
题目14:查询没有修过张三老师讲授的任何一门课程的学生姓名
SQL实现
SELECT
st.s_name
FROM
Student st
WHERE
st.s_id NOT IN (
SELECT
s_id
FROM
Score
GROUP BY
c_id,
s_id
HAVING
c_id IN ( SELECT c.c_id FROM Course c, Teacher t WHERE t.t_name = "张三" AND t.t_id = c.t_id )
)
结果如下:
题目15:查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SQL实现
SELECT
st.s_id,
st.s_name,
new_table.avg_score
FROM
Student st,
(
SELECT
s.s_id,
AVG( s.s_score ) avg_score
FROM
Score s
WHERE
s.s_score < 60 GROUP BY s.s_id HAVING COUNT( s_id ) >= 2
) new_table
WHERE
st.s_id = new_table.s_id
结果如下:
题目16:检索01课程分数小于60,按分数降序排列的学生信息
SQL实现
SELECT
st.*,
s.s_score
FROM
Student st
JOIN Score s ON st.s_id = s.s_id
AND s.c_id = "01"
AND s.s_score < 60
ORDER BY
s.s_score DESC
结果如下:
题目17:按平均成绩从高到低(降序)显示所有学生的所有课程的成绩以及平均成绩
SQL实现
SELECT
s.s_id,
( SELECT s_score FROM Score WHERE s_id = s.s_id AND c_id = "01" ) AS "语文",
( SELECT s_score FROM Score WHERE s_id = s.s_id AND c_id = "02" ) AS "数学",
( SELECT s_score FROM Score WHERE s_id = s.s_id AND c_id = "03" ) AS "英语",
ROUND(AVG(s_score),2) "平均分"
FROM Score s
GROUP BY s.s_id
ORDER BY 5 DESC
结果如下:
题目18:查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率;及格:>=60,中等为:70-80,优良为:80-90,优秀为:>=90
SQL实现
SELECT
s.c_id 课程编号,
c.c_name 课程名称,
MAX( s.s_score ) 最高分,
MIN( s.s_score ) 最低分,
ROUND( AVG( s.s_score ), 2 ) 平均分,
round(100 * SUM(CASE WHEN s.s_score>=60 THEN 1 ELSE 0 END)/SUM(CASE WHEN s.s_score THEN 1 ELSE 0 END),2) 及格率,
round(100 * SUM(CASE WHEN s.s_score>=70 AND s.s_score<80 THEN 1 ELSE 0 END)/SUM(CASE WHEN s.s_score THEN 1 ELSE 0 END),2) 中等率,
round(100 * SUM(CASE WHEN s.s_score>=80 AND s.s_score<90 THEN 1 ELSE 0 END)/SUM(CASE WHEN s.s_score THEN 1 ELSE 0 END),2) 优良率,
round(100 * SUM(CASE WHEN s.s_score>=90 THEN 1 ELSE 0 END)/SUM(CASE WHEN s.s_score THEN 1 ELSE 0 END),2) 优秀率
FROM
Score s,
Course c
WHERE
s.c_id = c.c_id
GROUP BY
s.c_id
结果如下:
题目19:按照各科成绩进行排序,并且显示排名
SQL实现
题目20:查询学生的总成绩,并进行排名
SQL实现
SET @crank =0;
SELECT b.s_name, b.all_score, @crank := @crank +1 AS rank FROM(
SELECT
st.s_name,
ss.all_score
FROM
Student st,
( SELECT s_id, SUM( s_score ) all_score FROM Score GROUP BY s_id ) ss
WHERE
st.s_id = ss.s_id
ORDER BY
all_score DESC) b
结果如下: