MySQL练习题

本文提供了一系列关于学生、课程、教师和成绩表的MySQL查询实例,包括查询特定课程成绩对比、平均成绩筛选、教师授课学生信息、未修特定课程学生、课程全修学生、课程部分修习学生以及未学过特定教师课程的学生等复杂查询操作,展示了SQL在数据查询中的应用。
摘要由CSDN通过智能技术生成

1.MySQL练习题

建表

创建需要的表以及数据:

-- 学生表
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) NOT NULL COMMENT '学生id',
  `c_id` varchar(20) NOT NULL COMMENT '课程id',
  `s_score` int(3) DEFAULT NULL COMMENT '成绩',
  PRIMARY KEY (`s_id`,`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 插入学生表测试数据
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.1查询’01’课程比’02’课程成绩高的学生的信息及课程分数

-- 方法1
select 
a.*
,b.s_score as 1_score  
,c.s_score as 2_score
from Student a
join Score b on a.s_id = b.s_id  and b.c_id = '01'   -- 两个表通过学号连接,指定01
left join Score c on a.s_id = c.s_id and c.c_id='02' or c.c_id is NULL -- 指定02,或者c中的c_id直接不存在
-- 为NULL的条件可以不存在,因为左连接中会直接排除c表中不存在的数据,包含NULL
where b.s_score > c.s_score;   -- 判断条件
-- 方法2:直接使用where语句
select 
a.*
,b.s_score as 1_score
,c.s_score as 2_score
from Student a, Score b, Score c
where a.s_id=b.s_id   -- 列出全部的条件
and a.s_id=c.s_id
and b.c_id='01'
and c.c_id='02'
and b.s_score > c.s_score;   -- 前者成绩高

1.2查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩

-- 执行顺序:先执行分组,再执行avg平均操作
SELECT
	b.s_id,
	b.s_name,
	AVG( a.s_score ) AS avgs,
	round( avg( a.s_score ), 2 ) AS avg_score -- 保留两位小数
FROM
	student b
	LEFT JOIN score a ON b.s_id = a.s_id 
-- JOIN score a ON b.s_id = a.s_id -- 不用left join 则不会查出没有成绩的学生
GROUP BY
	b.s_id 
HAVING
	avgs >= 60 
ORDER BY
	avgs DESC;

1.3查询学过张三老师授课的同学的信息

-- 方法1,常用
select s.* from Teacher t
left join Course c on t.t_id=c.t_id  -- 教师表和课程表
left join Score sc on c.c_id=sc.c_id  -- 课程表和成绩表
left join Student s on s.s_id=sc.s_id  -- 成绩表和学生信息表
where t.t_name='张三';
-- 方法2
select s1.* 
from Student s1
join Score s2 
on s1.s_id=s2.s_id 
where s2.c_id in (
  select c_id from Course c where t_id=(  -- 1. 通过老师找出其对应的课程
    select t_id from Teacher t where t_name='张三'
  )
)

1.4找出没有学过张三老师课程的学生

使用反查:先查出有张三课的学生,再去过滤

	-- 方法1
select * 
from Student s1
where s1.s_id not in (
	SELECT
		s2.s_id 
	FROM
		Student s2
		JOIN Score s3 ON s2.s_id = s3.s_id 
	WHERE
		s3.c_id IN (
		SELECT
			c.c_id 
		FROM
			Course c
			JOIN Teacher t ON c.t_id = t.t_id 
		WHERE
			t_name = '张三' 
		)
);
	-- 方法2
SELECT
	* 
FROM
	Student s1 
WHERE
	s1.s_id NOT IN (
	SELECT
		s.s_id 
	FROM
		Teacher t
		LEFT JOIN Course c ON t.t_id = c.t_id -- 教师表和课程表
		LEFT JOIN Score sc ON c.c_id = sc.c_id -- 课程表和成绩表
		LEFT JOIN Student s ON s.s_id = sc.s_id -- 成绩表和学生信息表
	WHERE
	t.t_name = '张三' 
	);
-- 方法3,使用NOT EXISTS,请尽量不要使用not in(它会调用子查询),而尽量使用not exists(它会调用关联子查询)
SELECT
	* 
FROM
	Student s1 
WHERE
	NOT EXISTS (
	SELECT
		1 
	FROM
		(
		SELECT
			s.s_id,
			t.t_name 
		FROM
			Teacher t
			LEFT JOIN Course c ON t.t_id = c.t_id -- 教师表和课程表
			LEFT JOIN Score sc ON c.c_id = sc.c_id -- 课程表和成绩表
			LEFT JOIN Student s ON s.s_id = sc.s_id -- 成绩表和学生信息表
		WHERE
			t.t_name = '张三' 
		) c 
	WHERE
	c.s_id = s1.s_id 
	);

1.5查询学过编号为01,并且学过编号为02课程的学生信息

-- 方法1:通过自连接实现
SELECT
	s1.* 
FROM
	Student s1 
WHERE
	s_id IN (
	SELECT
		s2.s_id 
	FROM
		Score s2
		JOIN Score s3 ON s2.s_id = s3.s_id 
	WHERE
		s2.c_id = '01' 
		AND s3.c_id = '02' 
	);
	-- 方法2:直接通过where语句实现
SELECT
	s1.* 
FROM
	Student s1,
	Score s2,
	Score s3 
WHERE
	s1.s_id = s2.s_id 
	AND s1.s_id = s3.s_id 
	AND s2.c_id = 01 
	AND s3.c_id = 02;
	-- 方法3:两个子查询
-- 1. 先查出学号
SELECT
	sc1.s_id 
FROM
	( SELECT * FROM Score s1 WHERE s1.c_id = '01' ) sc1,
	( SELECT * FROM Score s1 WHERE s1.c_id = '02' ) sc2 
WHERE
	sc1.s_id = sc2.s_id;
	-- 2.找出学生信息
SELECT
	* 
FROM
	Student 
WHERE
	s_id IN (
	SELECT
		sc1.s_id -- 指定学号是符合要求的
	FROM
		( SELECT * FROM Score s1 WHERE s1.c_id = '01' ) sc1,
		( SELECT * FROM Score s1 WHERE s1.c_id = '02' ) sc2 
	WHERE
		sc1.s_id = sc2.s_id 
	);
	-- 方法4,使用EXISTS
SELECT
	s1.* 
FROM
	Student s1 
WHERE
	EXISTS ( SELECT 1 FROM score c WHERE c.s_id = s1.s_id AND c.c_id = '01' ) 
	AND EXISTS ( SELECT 1 FROM score c2 WHERE c2.s_id = s1.s_id AND c2.c_id = '02' );

1.6查询学过01课程,但是没有学过02课程的学生信息

-- 方法1:根据两种修课情况来判断
SELECT
	s1.* 
FROM
	Student s1 
WHERE
	s1.s_id IN ( SELECT s_id FROM Score WHERE c_id = '01' ) -- 修过01课程,要保留
	AND s1.s_id NOT IN ( SELECT s_id FROM Score WHERE c_id = '02' );-- 哪些人修过02,需要排除
-- 方法2:先把06号学生找出来 
SELECT
* 
FROM
	Student 
WHERE
	s_id IN ( SELECT s_id FROM Score WHERE c_id = '01' -- 修过01课程的学号
	AND s_id NOT IN ( SELECT s_id -- 同时学号不能在修过02课程中出现
	FROM Score WHERE c_id = '02' ) );
	-- 方法3,使用  EXISTS ,NOT EXISTS
SELECT
	s1.* 
FROM
	Student s1 
WHERE
	EXISTS ( SELECT 1 FROM score c WHERE c.s_id = s1.s_id AND c.c_id = '01' ) 
	AND NOT EXISTS ( SELECT 1 FROM score c2 WHERE c2.s_id = s1.s_id AND c2.c_id = '02' );

1.7查询没有学全所有课程的同学的信息

	-- 方法一:
SELECT
	* 
FROM
	student 
WHERE
	s_id IN ( SELECT s_id FROM score GROUP BY s_id HAVING COUNT( s_id ) != 3 );
	-- 方法二:
SELECT
	* 
FROM
	student d 
WHERE
	d.s_id IN (
	SELECT
		e.s_id 
	FROM
		score e 
	WHERE
		e.s_id NOT IN (
		SELECT
			a.s_id 
		FROM
			score a
			JOIN score b ON a.s_id = b.s_id 
			AND b.c_id = '02'
			JOIN score c ON a.s_id = c.s_id 
			AND c.c_id = '03' 
		WHERE
			a.c_id = '01' 
		) 
	);
	-- 上述两种方法结果都少了没有选课的8号学生,但看具体条件是否需要查出
-- 方法3,使用  EXISTS ,先查出已经学完所有的人,再反查,就能查出8
SELECT
	* 
FROM
	student d 
WHERE
	d.s_id NOT IN (
	SELECT
		s1.s_id 
	FROM
		Student s1 
	WHERE
		EXISTS ( SELECT 1 FROM score c WHERE c.s_id = s1.s_id AND c.c_id = '01' ) 
	AND EXISTS ( SELECT 1 FROM score c2 WHERE c2.s_id = s1.s_id AND c2.c_id = '02' ) 
	AND EXISTS ( SELECT 1 FROM score c3 WHERE c3.s_id = s1.s_id AND c3.c_id = '03' ));

1.8查询和"01"号的同学学习的课程完全相同的其他同学的信息

-- 方法1
-- 将group by产生的同一个分组中的值连接起来,返回一个字符串结果
-- 再去匹配字符串一样的学生(注意字符拼接前要排序)
SELECT
	t1.s_id 
FROM
	( SELECT s_id, group_concat( c_id ORDER BY c_id ) AS a FROM score GROUP BY s_id ) t1 
WHERE t1.s_id != '01' and
	t1.a = ( SELECT group_concat( c_id ORDER BY c_id ) AS a FROM score WHERE s_id = '01' GROUP BY s_id );
-- 方法2
SELECT* FROM student 
WHERE
	s_id IN (
	SELECT DISTINCT
		s_id 
	FROM
		score 
	WHERE
		s_id != '01' 
		AND c_id IN ( SELECT c_id FROM score WHERE s_id = '01' ) 
	GROUP BY
		s_id 
	HAVING
		COUNT( 1 )=(
		SELECT
			COUNT( 1 ) 
		FROM
			score 
		WHERE
			s_id = '01' 
		) 
	) ;

1.9 查询没学过张三老师讲过任何一门课的学生

SELECT student.*  FROM student  WHERE
	student.s_id NOT IN (
	SELECT s.s_id  FROM score s  WHERE
		s.c_id IN ( SELECT course.c_id FROM course,teacher WHERE teacher.t_id  =course.t_id and teacher.t_name = '张三' ) GROUP BY s.s_id );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值