[Mysql] 1.MySQL查询练习

2019.11.21更新:重新看了下之前的东西,发现几个错误,做一个更正


最近在初学MySQL,在网上找相关查询语句练习的时候发现一些答案有一些问题,这边做出了更正,当然也不能保证完全正确,有更好的写法也欢迎交流。:-)

前提:

设有一数据库包括:学生表(Student)、课程表(Course)、成绩表(Score)、教师信息表(Teacher)

#以下的语句可以直接复制使用

#学生表(Student)

CREATE TABLE student
(
sno VARCHAR(3) NOT NULL,
sname VARCHAR(4) NOT NULL,
ssex VARCHAR(2) NOT NULL,
sbirthday DATETIME,
class VARCHAR(5)
);

#课程表(Course)

CREATE TABLE course
(
cno VARCHAR(5) NOT NULL,
cname VARCHAR(10) NOT NULL,
tno VARCHAR(10) NOT NULL
);

#成绩表(Score)

CREATE TABLE score
(
sno VARCHAR(3) NOT NULL,
cno VARCHAR(5) NOT NULL,
degree NUMERIC(10, 1) NOT NULL
);

#教师信息表(Teacher)

CREATE TABLE teacher
(
tno VARCHAR(3) NOT NULL,
tname VARCHAR(4) NOT NULL,
tsex VARCHAR(2) NOT NULL,
tbirthday DATETIME NOT NULL,
prof VARCHAR(6),
depart VARCHAR(10) NOT NULL
);

#插入学生名单

INSERT INTO student VALUES
('108','曾华','男','1977-09-01','95033'),
('105','匡明','男','1975-10-02','95031'),
('107','王丽','女','1976-01-23','95033'),
('101','李军','男','1976-02-20','95033'),
('109','王芳','女','1975-02-10','95031'),
('103','陆君','男','1974-06-03','95031');

#插入课程名单

INSERT INTO course VALUES
('3-105', '计算机导论','825'),
('3-245', '操作系统','804'),
('6-166', '数字电路','856'),
('9-888', '高等数学','831');

#插入成绩表

INSERT INTO score (sno,cno,degree) VALUES
('103', '3-245','86'),
('105', '3-245','75'),
('109', '3-245','68'),
('103', '3-105','92'),
('105', '3-105','88'),
('109', '3-105','76'),
('101', '3-105','64'),
('107', '3-105','91'),
('108', '3-105','78'),
('101', '6-166','85'),
('107', '6-166','79'),
('108', '6-166','81');

#插入教师表

INSERT INTO teacher VALUES
('804','李诚','男','1958-12-02','副教授','计算机系'),
('856','张旭','男','1969-03-12','讲师','电子工程系'),
('825','王萍','女','1972-05-05','助教','计算机系'),
('831','刘冰','女','1977-08-14','助教','电子工程系');
1.查询student表中的所有记录的Sname、Ssex和Class列。
SELECT sname, ssex, class FROM student;

2.查询教师所有的单位即不重复的depart列。
# DISTINCT的使用
SELECT DISTINCT depart FROM teacher;

3.查询student表的所有记录。
SELECT * FROM student;

4.查询score表中成绩在60到80之间的所有记录。
# BETWEEN A AND B的使用,包含A B两个端点值
SELECT * FROM score
WHERE degree BETWEEN 60 AND 80;

5.查询score表中成绩为85,86或88的记录。
# IN的使用
SELECT * FROM score
WHERE degree IN ('85','86','88');

6.查询student表中“95031”班或性别为“女”的同学记录。 
# OR的使用
# 2019.11.21更新:这次在做的时候写了个union,属实憨批,运行时间翻了三倍,不要用union
SELECT * FROM student
WHERE class = '95301' OR ssex = '女';

7.以class降序查询student表的所有记录。
# ORDER BY及ASC DESC的使用,且ORDER BY 要放在查询的最后
SELECT * FROM student
ORDER BY class desc;

8.以cno升序、degree降序查询score表的所有记录。
SELECT * FROM score
ORDER BY cno asc, degree desc;

9.查询“95031”班的学生人数。
# 2019.11.21更新:COUNT的使用
# 有主键多列:count(主键列名) > count(1) > count(*)
# 无主键多列:count(1) > count(一般列名) > count(*)
# 原答案:
SELECT COUNT(*) FROM student
WHERE class = '95031';
# 新答案:
SELECT COUNT(1) FROM student
WHERE class = '95031';

10.查询score表中的最高分的学生学号和课程号。
# MAX函数及子查询的使用
SELECT sno, cno FROM score a
WHERE degree = (select MAX(degree) FROM score);

11.查询‘3-105’号课程的平均分。
SELECT CNO, AVG(degree) FROM score
WHERE cno = '3-105'

12.查询score表中至少有5名学生选修的,并以3开头的课程的平均分数。
# AVG,MIN,MAX等聚合函数要与GROUP BY…HAVING 的使用。
SELECT cno, AVG(degree) FROM score
GROUP BY cno
HAVING count(*) >= 5 AND cno like '3%';
# 或者这样也可以,这个更快
SELECT cno, AVG(degree) FROM score
WHERE cno like '3%'
GROUP BY cno
HAVING count(*) >= 5;
# 这样不行,WHERE后的条件不能用聚合函数,这点非常重要!
SELECT cno, AVG(degree) FROM score
WHERE count(*) >= 5
GROUP BY cno
HAVING cno like '3%';
# 2019.11.21更新:HAVING和WHERE两者很接近,之前有段时间陷入了只要HAVING的东西就一定要SELECT出来,后来突然发现并没有必要,当一个特殊的WHERE就好

13.查询最低分大于70,最高分小于90的sno列。
# AVG,MIN,MAX等聚合函数要与GROUP BY…HAVING 的使用。
SELECT sno, degree FROM score
GROUP BY sno
HAVING MAX(degree) < 90 AND MIN(degree) > 70;

14.查询所有学生的sname、cno和degree列。
# 两表之间有共同元素时采用JOIN连接两表
SELECT a.sname, b.cno, b.degree FROM student a
JOIN score b ON a.sno = b.sno; 

15.查询所有学生的sname、cname和degree列。
# 此处SELECT FORM score, 因为其与另两表均有共同元素
SELECT b.sname, c.cname, a.degree FROM score a 
JOIN student b ON a.sno = b.sno 
JOIN course c ON a.cno = c.cno

16.查询“95033”班学生的平均分。
SELECT cno, AVG(degree) FROM score 
WHERE sno IN (SELECT sno FROM student WHERE class = '95033')
GROUP BY cno;

17.假设使用如下命令建立了一个grade表:
# 有一些字段为Mysql的保留字段 如RANK 要加上``引用起来才可以,不然会报错,使用时正常使用即可。
CREATE TABLE grade(
low INT(3),
upp INT(3), 
`Rank` CHAR(1)
);
INSERT INTO grade VALUES
(90,100,'A'),
(80,89,'B'),
(70,79,'C'),
(60,69,'D'),
(0,59,'E');

查询所有同学的Sno、Cno和rank列。
# JOIN..ON不仅可以可以用作A.a = B.b 同样也可以这样使用
SELECT a.sno, a.cno, a.degree, b.rank FROM score a
JOIN grade b ON
a.degree BETWEEN b.low AND b.upp

18.查询选修“3-105”课程的成绩高于“109”号同学成绩的所有同学的记录。
SELECT * FROM score
WHERE cno = '3-105'
AND degree > (SELECT degree FROM score WHERE cno = '3-105' AND sno = 109)

19.查询score中选学多门课程的同学中分数为非最高分成绩的记录。
# 要与最高分比较可以用所要的JOIN..ON最高分生成的表,并判断两个分数的关系
SELECT a.sno, a.cno, a.degree FROM score a
JOIN (SELECT cno, MAX(degree) standard FROM score GROUP BY cno) b
ON a.cno = b.cno
WHERE a.degree < b.standard 

20.查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录。
SELECT * FROM score
WHERE degree > (SELECT degree FROM score WHERE sno = '109' AND cno = '3-105')

21.查询和学号为108的同学同年出生的所有学生的sno、sname和sbirthday列。
SELECT a.sno, a.sname, a.sbirthday FROM student a
WHERE YEAR(a.sbirthday) = (SELECT YEAR(b.sbirthday) FROM student b WHERE b.sno = '108' )

22.查询“张旭“教师任的学生成绩。
SELECT b.sno, a.cno, b.degree, c.tname FROM course a
JOIN score b ON a.cno = b.cno
JOIN teacher c ON a.tno = c.tno
WHERE c.tno = (SELECT tno FROM teacher WHERE tname = '张旭')
2019.11.21更新:一个更快的答案
SELECT sc.*, t1.cname FROM score sc 
RIGHT JOIN 
( SELECT co.*, te.tname FROM course co LEFT JOIN teacher te ON co.tno = te.tno WHERE te.tname = '张旭' ) t1 
ON sc.cno = t1.cno

23.查询选修某课程的同学人数多于5人的教师姓名。
SELECT a.tno, b.tname, COUNT(c.cno) number FROM course a
JOIN teacher b ON a.tno = b.tno
JOIN score c ON a.cno = c.cno
GROUP BY a.tno
HAVING COUNT(c.cno) > 5

24.查询95033班和95031班全体学生的记录。
SELECT * FROM student
WHERE class IN ('95033', '95031')

25.查询存在有85分以上成绩的课程cno。
SELECT b.cno, b.cname, a.degree FROM score a
JOIN course b ON a.cno = b.cno
GROUP BY b.cno
HAVING MAX(a.degree) > 85

26.查询出“计算机系“教师所教课程的成绩表及对应教师信息。
SELECT b.depart, b.tname, a.cno, a.cname, c.sno, c.degree FROM course a
JOIN teacher b ON a.tno = b.tno
JOIN score c ON a.cno = c.cno
WHERE b.depart = '计算机系'

27.查询属于“计算机系”与“电子工程系“的不同职称的教师的tname和prof。
SELECT tname, prof, depart FROM teacher
WHERE depart = '计算机系' OR depart = '电子工程系'
GROUP BY prof
HAVING COUNT(prof) = 1

28.查询选修编号为“3-105”且成绩高于选修编号为“3-245”课程的同学的cno、sno和degree。
SELECT * FROM score
WHERE cno = '3-105'
AND degree > (SELECT MIN(degree) FROM score WHERE cno = '3-245')

29.查询所有教师和同学的name、sex和birthday。
SELECT tname name, tsex sex, tbirthday birthday FROM teacher
UNION
SELECT sname name, ssex sex, sbirthday birthday FROM student

30.查询成绩比该课程平均成绩低的同学的成绩表。
SELECT * FROM score a
JOIN (SELECT cno, AVG(degree) standard FROM score GROUP BY cno) b ON a.cno = b.cno
WHERE a.degree < b.standard

31.查询所有任课教师的tname和depart。
# 2019.11.21更新:之前做错了,更正一下
# 原答案:
SELECT tname, depart FROM teacher
WHERE tno IN (SELECT tno FROM course)
# 新答案:
SELECT tname, depart FROM teacher te 
WHERE tno IN ( SELECT t1.tno FROM ( SELECT sc.cno, co.tno FROM score sc LEFT JOIN course co ON sc.cno = co.cno ) t1 )


32.查询所有未讲课的教师的tname和depart。
# 2019.11.21更新:之前做错了,更正一下
# 原答案:
SELECT tname, depart FROM teacher
WHERE tno NOT IN (SELECT tno FROM course)
# 新答案:
SELECT tname, depart FROM teacher te 
WHERE tno IN ( SELECT t1.tno FROM ( SELECT sc.cno, co.tno FROM score sc LEFT JOIN course co ON sc.cno = co.cno ) t1 )

33.查询至少有2名男生的班号。
# 2019.11.21更新:同理,更正一下
# 原答案:
SELECT class, COUNT(*) FROM student
WHERE ssex = '男'
GROUP BY class
HAVING COUNT(*) >= 2
# 新答案:
SELECT class, COUNT(*) FROM student
WHERE ssex = '男'
GROUP BY class
HAVING COUNT(1) >= 2

34.查询不姓王的同学信息。
SELECT * FROM student
WHERE sname NOT LIKE "王%"

35.查询student表中每个学生的姓名和年龄。
SELECT sname, (YEAR(NOW())-YEAR(sbirthday)) age FROM student

36.查询student表中最大和最小的sbirthday日期值。
SELECT MAX(YEAR(sbirthday)) youngest, MIN(YEAR(sbirthday)) oldest FROM student

37.以班号和年龄从大到小的顺序查询student表中的全部记录。
SELECT * FROM student
ORDER BY class DESC, sbirthday ASC

38.查询“男”教师及其所上的课程。
SELECT a.tno, a.tname, a.tsex, b.cname FROM teacher a
JOIN course b ON a.tno = b.tno
WHERE a.tsex = '男'

39.查询最高分同学的sno、cno和degree列。
SELECT sno, cno, MAX(degree) FROM score
GROUP BY cno

40.查询所有选修“计算机导论”课程的“男”同学的成绩表。
SELECT a.sno, a.cno, b.cname, a.degree FROM score a
JOIN course b ON a.cno = b.cno
JOIN student c ON a.sno = c.sno
WHERE b.cname = '计算机导论'
AND c.ssex = '男'

41.查询和“李军”同性别的所有同学的sname。
SELECT sname FROM student
WHERE ssex = (SELECT ssex FROM student WHERE sname = '李军')
AND sname != '李军'

42.查询和“李军”同性别并同班的同学sname。
SELECT sname FROM student
WHERE ssex = (SELECT ssex FROM student WHERE sname = '李军')
AND class = (SELECT class FROM student WHERE sname = '李军')
AND sname != '李军'

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值