前言
本文是转载自
https://blog.csdn.net/woshinidedege/article/details/78659202
并根据自己的理解以及使用的mysql的5.5.37版本进行重新修改,其中这个版本无between,top关键字。
此文章只作为参考,其中也有问题所在,所要写的总结也没有完成,等待慢慢完善
SQL测试数据:
/*
SQLyog v10.2
MySQL - 5.5.37 : Database - testsql
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`testsql` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `testsql`;
/*Table structure for table `course` */
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`Cid` int(10) NOT NULL AUTO_INCREMENT,
`Cname` varchar(10) DEFAULT NULL,
`Tid` int(10) DEFAULT NULL,
PRIMARY KEY (`Cid`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
/*Data for the table `course` */
insert into `course`(`Cid`,`Cname`,`Tid`) values (1,'语文',1),(2,'数学',2),(3,'英语',3),(4,'物理',4),(5,'化学',5),(6,'政治',6),(7,'历史',7);
/*Table structure for table `sc` */
DROP TABLE IF EXISTS `sc`;
CREATE TABLE `sc` (
`Sid` int(10) NOT NULL,
`Cid` int(10) DEFAULT NULL,
`score` int(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `sc` */
insert into `sc`(`Sid`,`Cid`,`score`) values (1,1,88),(1,2,55),(1,3,77),(1,4,77),(1,5,77),(1,6,100),(2,1,33),(2,2,44),(2,3,56),(2,4,89),(2,5,99),(2,6,100),(3,1,33),(3,2,67),(3,3,67),(3,4,87),(3,5,90),(3,6,56),(4,1,34),(4,2,65),(4,3,75),(4,4,45),(4,5,97),(4,6,67),(5,1,87),(5,2,75),(5,3,56),(5,4,34),(5,5,65),(5,6,45),(6,2,46),(6,3,76),(6,4,56),(6,5,87),(6,6,56),(6,1,23),(7,1,87),(7,2,56),(7,3,86),(7,4,56),(7,5,97),(7,6,56),(8,1,65),(8,2,34),(8,3,64),(8,4,45),(8,5,75),(8,6,45),(9,1,75),(9,2,34),(9,3,64),(9,4,75),(9,5,86),(9,6,45),(10,6,10),(10,1,34),(10,2,77),(10,3,12),(10,4,66),(10,7,57),(10,5,45);
/*Table structure for table `student` */
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`Sid` int(10) NOT NULL AUTO_INCREMENT,
`Sname` varchar(10) DEFAULT NULL,
`Sage` int(10) DEFAULT NULL,
`Ssex` varchar(10) DEFAULT NULL,
`Cus_id` int(10) DEFAULT NULL,
PRIMARY KEY (`Sid`),
KEY `FK8FFE823B61D74C29` (`Cus_id`),
CONSTRAINT `Cus_id` FOREIGN KEY (`Cus_id`) REFERENCES `course` (`Cid`),
CONSTRAINT `FK8FFE823B61D74C29` FOREIGN KEY (`Cus_id`) REFERENCES `student` (`Sid`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
/*Data for the table `student` */
insert into `student`(`Sid`,`Sname`,`Sage`,`Ssex`,`Cus_id`) values (1,'张一',12,'男',NULL),(3,'李爱国',16,'男',4),(4,'李文',12,'女',NULL),(5,'阿尔法',14,'男',NULL),(6,'李明',12,'男',NULL),(7,'文慧',12,'女',NULL),(8,'商新',14,'女',NULL),(9,'卢瑟福',12,'男',NULL),(10,'梅泰诺',13,'女',NULL),(11,'熊小',12,'男',NULL),(12,'张一',15,'女',NULL);
/*Table structure for table `teacher` */
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
`Tid` int(10) NOT NULL AUTO_INCREMENT,
`Tname` varchar(10) DEFAULT NULL,
PRIMARY KEY (`Tid`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
/*Data for the table `teacher` */
insert into `teacher`(`Tid`,`Tname`) values (1,'123'),(2,'王武'),(3,'张丽'),(4,'十五'),(5,'霸屏'),(6,'娃哩'),(7,'王武');
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
其中:
Student(Sid,Sname,Sage,Ssex)学生表
Sid:学号
Sname:学生姓名
Sage:学生年龄
Ssex:学生性别
Course(Cid,Cname,Tid)课程表
Cid:课程编号
Cname:课程名称
Tid:教师编号
SC(Sid,Cid,score)成绩表
Sid:学号
Cid:课程编号
score:成绩
Teacher(Tid,Tname)教师表
Tid:教师编号:
练习题:
1、查询“001”课程比“002”课程成绩高的所有学生的学号
SELECT a.`Sid` FROM (SELECT sid, score FROM sc WHERE cid=1) AS a ,(SELECT sid , score FROM sc WHERE cid =2) AS b
WHERE a.sid=b.sid AND a.score>b.score
2、查询平均成绩大于60分的同学的学号和平均成绩
SELECT sid ,AVG(score) FROM sc GROUP BY sid HAVING AVG(score)>60
3、查询所有同学的学号、姓名、选课数、总成绩
SELECT student.Sid, student.Sname, COUNT(sc.Cid), SUM(score) FROM student LEFT OUTER JOIN SC ON student.Sid = SC.Sid GROUP BY Student.Sid, Sname
4、查询姓‘王’的老师的个数:
SELECT COUNT(*) FROM teacher WHERE tname LIKE '王%'
5、查询没有学过“王武”老师可的同学的学号、姓名:
SELECT sid , sname FROM student WHERE sid NOT IN (
SELECT sc.`Sid` FROM sc , course ,teacher WHERE sc.`Cid`=course.`Cid`
AND course.`tid`=teacher.`Tid` AND teacher.`Tname`='王武')
6、查询学过“王武”老师所教的所有课的同学的学号、姓名:
SELECT sc.`Sid` ,student.`Sname` ,sc.`Cid` FROM sc ,student WHERE sc.`Sid`=student.`Sid` AND sc.`Cid` IN
(SELECT course.`Cid` FROM course ,teacher WHERE
course.`Tid`=teacher.`Tid` AND teacher.`Tname`='王武')
7、查询学过“011”并且也学过编号“002”课程的同学的学号、姓名:
1、
SELECT sid ,sname FROM student WHERE sid IN
(SELECT sc.`Sid` FROM sc WHERE cid IN (1,2))
2、
SELECT Student.Sid,Student.Sname
FROM Student,SC WHERE Student.Sid=SC.Sid
AND SC.Cid='001'AND
EXISTS( SELECT * FROM SC AS SC_2 WHERE SC_2.Sid=SC.Sid AND SC_2.Cid='002');
8、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名:
1、
SELECT a.sid ,a.sname FROM
(SELECT sc.`Sid` ,sc.`Cid`,sc.`score`,student.`Sname` FROM sc ,student
WHERE sc.`Sid`=student.`Sid` AND sc.`Cid`=1)AS a ,
(SELECT sc.`Sid` ,sc.`Cid`,sc.`score`,student.`Sname` FROM sc ,student
WHERE sc.`Sid`=student.`Sid` AND sc.`Cid`=2)AS b
WHERE a.sid=b.sid AND a.score>b.score
2、
SELECT sid,sname FROM (SELECT sc.`Sid` ,sname ,score ,
(SELECT sc.`score` FROM sc WHERE sc.`Sid`=student.`Sid` AND sc.`Cid`=1) AS score2
FROM student ,sc WHERE sc.`Sid`=student.`Sid` AND sc.`Cid`=2) AS scc WHERE score2>score
9、查询所有课程成绩小于60的同学的学号、姓名:
SELECT sc.`Sid` ,student.`Sname` ,sc.`Cid` FROM sc ,student WHERE sc.`Sid`=student.`Sid`
AND sc.`score`<60
10、查询没有学全所有课的同学的学号、姓名:
SELECT sid ,sname FROM student WHERE sid NOT IN
(SELECT sid FROM sc GROUP BY sid HAVING COUNT(cid)=(SELECT COUNT(*) FROM course))
11、查询至少有一门课与学号为“1001”同学所学相同的同学的学号和姓名:
SELECT student.`Sid`,student.`Sname` FROM sc ,student WHERE sc.`Sid`=student.`Sid`
AND sc.`Cid` IN
(SELECT cid FROM sc WHERE sc.`Sid`=1) GROUP BY sc.sid
12、查询至少学过学号为“001”同学所有一门课的其他同学学号和姓名;
SELECT DISTINCT student.`Sid`,student.`Sname` FROM sc ,student WHERE sc.`Sid`=student.`Sid`
AND sc.`Cid` IN
(SELECT cid FROM sc WHERE sc.`Sid`=1) GROUP BY sc.sid
13、把“SC”表中“123”老师教的课的成绩都更改为此课程的平均成绩:
UPDATE sc SET score=(SELECT AVG(score) FROM sc s WHERE sc.`Cid`=s.`Cid`)
WHERE cid IN (SELECT course.`Cid` FROM course,teacher WHERE course.`Tid`=teacher.`Tid`
AND teacher.`Tname`='123')
14、查询和“001”号的同学学习的课程完全相同的其他同学学号和姓名:
SELECT student.sid ,student.sname FROM student ,sc WHERE sc.`Sid`=student.`Sid`
AND sc.`cid` IN
(SELECT cid FROM sc WHERE sc.`Sid`=1) GROUP BY sc.`Sid`
HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.`Sid`=1)
15、删除学习“123”老师课的SC表记录:
DELETE sc FROM course ,teacher WHERE course.`Tid`=teacher.`Tid` AND sc.`Cid`=course.`Cid`
AND teacher.`Tname`='123'
16、向SC表中插入一些记录,这些记录要求符合以下条件:没有上过编号“003”课程的同学学号、
INSERT sc SELECT sid ,'002',(SELECT AVG(score) FROM sc WHERE cid=2)
FROM student WHERE sid NOT IN (SELECT sid FROM sc WHERE sc.`Cid`=3)
17、按平均成绩从高到低显示所有学生的“ 语文”、“数学”、“英语”三门的课程成绩,
按如下形式显示:学生ID, 语文,数学,英语,有效课程数,有效平均分:
SELECT sid ,
(SELECT sc.`score` FROM sc ,course WHERE sc.`Cid`=course.`Cid` AND sc.`Sid`=ss.sid AND course.`Cname`='语文') 语文,
(SELECT sc.`score` FROM sc ,course WHERE sc.`Cid`=course.`Cid` AND sc.`Sid`=ss.sid AND course.`Cname`='数学') 数学,
(SELECT sc.`score` FROM sc ,course WHERE sc.`Cid`=course.`Cid` AND sc.`Sid`=ss.sid AND course.`Cname`='英语') 英语,
COUNT(*)有效课程,
AVG(score)平均分
FROM sc ss GROUP BY sid ORDER BY AVG(score)
18、查询各科成绩最高和最低的分:以如下的形式显示:课程ID,最高分,最低分
SELECT cid ,MAX(score),MIN(score) FROM sc GROUP BY cid
19、按各科平均成绩从低到高和及格率的百分数从高到低顺序:
SELECT sc.`Cid` ,MAX(course.`Cname`) ,AVG(score),
100*SUM(CASE WHEN score>=60 THEN 1 ELSE 0 END)/COUNT(*) AS 及格百分数
FROM sc,course WHERE sc.`Cid`=course.`Cid` GROUP BY sc.`Cid` ORDER BY 及格百分数 DESC
20、查询如下课程平均成绩和及格率的百分数(用”1行”显示):语文(001),数学(002),英语 (003),物理(004):
SELECT cid , AVG(score) ,COUNT(*),100*SUM(CASE WHEN score>=60 THEN 1 ELSE 0 END)/COUNT(*) 及格百分数
FROM sc WHERE sc.`Cid` IN (SELECT cid FROM course WHERE cname IN ('语文','数学','英语','物理')
) GROUP BY cid
21、查询不同老师所教不同课程平均分从高到低显示:
SELECT sc.cid ,AVG(sc.score) FROM sc GROUP BY cid ORDER BY AVG(sc.score)DESC
22、查询如下课程成绩第3名到第6名的学生成绩单:
语文(001),数学(002),英语(003),物理(004):
SELECT sid ,score FROM sc WHERE cid IN
(SELECT cid FROM course WHERE cname IN ('语文','数学','英语','物理')) ORDER BY score DESC
LIMIT 2,4
23、统计下列各科成绩,各分数段人数:课程ID,课程名称,
[100-85],[85-70],[70-60],[ 小于60] :
SELECT sc.`Cid` ,course.`Cname`, sc.`score`,
SUM(CASE WHEN sc.`score`>85 AND sc.`score`<=100 THEN 1 ELSE 0 END) AS '[100-85]',
SUM(CASE WHEN sc.`score`>70 AND sc.`score`<=85 THEN 1 ELSE 0 END) AS '[85-70]',
SUM(CASE WHEN sc.`score`>60 AND sc.`score`<=70 THEN 1 ELSE 0 END) AS '[70-60]',
SUM(CASE WHEN sc.`score`<60 THEN 1 ELSE 0 END) AS '[ 小于60]'
FROM sc ,course WHERE sc.`Cid`=course.`Cid` GROUP BY sc.`Cid`
24、查询学生平均成绩及其名次:
SELECT sid ,AVG(score) AS 平均成绩, (@rownum := @rownum + 1) AS RANK
FROM sc ,(SELECT @rownum := 0) r GROUP BY sid ORDER BY 平均成绩 DESC
注:这么使用是先有了名次之后再按照平均成绩排序,所以不符合要求
SELECT 1+(SELECT COUNT( DISTINCT 平均成绩)
FROM (SELECT Sid,AVG(score) AS 平均成绩
FROM SC
GROUP BY Sid ) AS T1 WHERE 平均成绩 > T2.平均成绩) AS 名次,
Sid AS 学生学号,平均成绩
FROM (SELECT Sid,AVG(score) 平均成绩
FROM SC
GROUP BY Sid ) AS T2
ORDER BY 平均成绩 DESC;
注:这么写也有问题,就是当平均分相同时,排名是相同的,然后下一个不同的是不是顺位下一位
数字,而是跳到其在的排序位置,下一sql语句证明了这个情况,所以也有问题,以后完善
SELECT sid ,CJ ,
1+(SELECT COUNT(*) FROM (SELECT sid, score AS CJ FROM sc WHERE sid=1 GROUP BY cid)AS t1
WHERE t1.CJ>t2.CJ ) AS 名次
FROM (SELECT sid, score AS CJ FROM sc WHERE sid=1 GROUP BY cid)AS t2 ORDER BY CJ DESC
25、查询各科成绩前三名的记录(不考虑成绩并列情况):
SELECT t1.cid AS 课程ID , t1.sid AS 学号 , t1.score AS 成绩 FROM sc t1
WHERE EXISTS (SELECT COUNT(*) FROM sc AS t2 WHERE t1.cid = t2.cid AND t1.score<t2.score
HAVING COUNT(*)<=3 ORDER BY t2.score DESC) AND t1.score IS NOT NULL ORDER BY t1.cid
26、查询每门课程被选修的学生数:
SELECT cid ,COUNT(sid) FROM sc WHERE score IS NOT NULL GROUP BY cid
27、查询出只选修一门课程的全部学生的学号和姓名:
SELECT student.`Sid` 学号 , student.`Sname` FROM student , sc WHERE sc.`Sid`=student.`Sid`
GROUP BY sc.`Sid` , student.`Sname` HAVING COUNT(sc.cid)=6
28、查询男生、女生人数:
SELECT SUM(CASE WHEN Ssex='男' THEN 1 ELSE 0 END) AS 男生人数 ,
SUM(CASE WHEN Ssex='女' THEN 1 ELSE 0 END) AS 女生人数 FROM student
29、查询姓“张”的学生名单:
SELECT * FROM student WHERE sname LIKE '张%'
30、查询同名同姓的学生名单,并统计同名人数:
SELECT sname , COUNT(*) FROM student GROUP BY sname HAVING COUNT(sname)>1
31、1981年出生的学生名单(注:student表中sage列的类型是datetime):
SELECT sname , CONVERT(CHAR(11),datepart(YEAR,sage)) AS age
FROM student CONVERT(CHAR(11),datepart(YEAR,sage))>1981
32、查询平均成绩大于33的所有学生的学号、姓名和平均成绩:
SELECT student.`Sid` 学生学号 , student.`Sname` 学生姓名 , AVG(sc.score) 平均成绩
FROM student ,sc WHERE student.`Sid`=sc.`Sid` GROUP BY student.`Sid`,student.`Sname`
HAVING AVG(sc.score)>33
33、查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列:
SELECT cid ,AVG(score) FROM sc GROUP BY cid ORDER BY AVG(score),cid DESC
34、查询课程名称为“数据库”,且分数低于60的学生名字和分数:
SELECT course.`Cname` 课程 , student.`Sname` 学生名字 , sc.`score` 学生分数
FROM course , sc ,student WHERE course.`Cid`=sc.`Cid` AND sc.`Sid`=student.`Sid`
AND course.`Cname`='英语' AND sc.`score`<60
35、查询所有学生的选课情况:
SELECT student.`Sid` ,student.`Sname`,course.`Cid` ,course.`Cname`
FROM course , sc , student WHERE course.`Cid`=sc.`Cid` AND sc.`Sid`=student.`Sid`
36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数:
SELECT DISTINCT student.`Sname` ,course.`Cname` ,sc.`score`
FROM course , sc , student WHERE course.`Cid`=sc.`Cid` AND sc.`Sid`=student.`Sid`
AND sc.`score`>70
37、查询不及格的课程,并按课程号从大到小的排列:
SELECT sc.`Cid` , sc.`Sid`, sc.`score` FROM sc WHERE sc.`score`<60 ORDER BY sc.cid DESC
38、查询课程编号为“003”且课程成绩在80分以上的学生的学号和姓名:
SELECT sc.`Sid` , student.`Sname` FROM sc ,student WHERE sc.`Sid`=student.`Sid` AND
sc.`score`>80 AND sc.`Cid`=3
39、求选了课程的学生人数:
SELECT COUNT(score) FROM sc
40、查询选修“123”老师所授课程的学生中,成绩最高的学生姓名及其成绩:
1、
SELECT student.`Sid` ,student.`Sname` ,b.`score` FROM student , sc b,course, teacher
WHERE EXISTS(SELECT COUNT(*) FROM sc c WHERE c.sid=b.`Sid` AND c.score>b.`score`
AND teacher.`Tname`='123'
HAVING COUNT(score)=1 ORDER BY c.score DESC)
AND student.`Sid`=b.`Sid` AND b.`Cid`=course.`Cid`
AND course.`Tid`=teacher.`Tid` GROUP BY b.`Cid`
2、
SELECT student.sname,score
FROM student,sc,course c, teacher
WHERE student.sid=sc.Sid AND sc.cid=c.cid
AND c.Tid=teacher.Tid
AND teacher.tname='123'
AND sc.score=(SELECT MAX(score) FROM sc WHERE cid=c.cid);
41、查询各个课程及相应的选修人数:
SELECT cid ,COUNT(score) FROM sc GROUP BY cid
42、查询不同课程成绩相同的学生和学号、课程号、学生成绩:
SELECT DISTINCT c.cid , c.sid ,c1.score FROM sc c, sc c1
WHERE c.score=c1.score AND c.cid!=c1.cid
43、查询每门课程成绩最好的前两名:
SELECT c.cid , c.sid ,c.score FROM sc c WHERE EXISTS(SELECT COUNT(*) FROM sc c1
WHERE c.cid=c1.cid AND c.score<c1.score HAVING COUNT(*)<2 ORDER BY c1.score DESC)
AND c.score IS NOT NULL ORDER BY c.cid ,c.sid
44、统计每门课程的学生选修人数(超过6人的课程才统计)。要求输出课程号和选修人数,
查询结果按人数降序排序,若人数相同,按课程号升序排序:
SELECT sc.`Cid` ,COUNT(sc.sid) FROM sc GROUP BY cid ORDER BY COUNT(sc.`Sid`) DESC, sc.cid
45、检索至少选修两门课程的学生学号:
SELECT sid FROM sc GROUP BY sid HAVING COUNT(*)>=6
46、查询全部学生选修的课程和课程号和课程名:
1、
SELECT sc.`Cid`,sc.`Sid`,course.`Cname` FROM sc ,course WHERE sc.`Cid`=course.`Cid`
GROUP BY sc.`Cid`
2、
SELECT cid,cname FROM course WHERE cid IN (SELECT cid FROM sc GROUP BY cid)
47、查询没学过”叶平”老师讲授的任一门课程的学生姓名:
SELECT sname FROM student WHERE sid NOT IN
(SELECT sc.`Sid` FROM teacher,course, sc WHERE teacher.`Tid`=course.`Tid`
AND course.`Cid`=sc.`Cid` AND teacher.`Tname`='123')
48、查询两门以上不及格课程的同学的学号以及其平均成绩:
SELECT sid ,AVG(score) FROM sc WHERE sid IN
(SELECT sid FROM sc c1 WHERE c1.score<60 GROUP BY c1.sid HAVING COUNT(*)>2)
49、检索“004”课程分数小于60,按分数降序排列的同学学号:
SELECT sid ,score FROM sc WHERE cid=4 AND score<60 ORDER BY score DESC
50、删除“002”同学的“001”课程的成绩:
DELETE FROM sc WHERE sid=1 AND cid=2
总结:
建议在练习这50道SQL练习题前先了解:
1、SQL的连接类型,有内连接,外连接以及他们之间的区别,其中自连接是一种连接用法,不是类型
2、关键字,distinct(去重),exists(存在),in(在),not in(不在),convert,case,isnull,以及其用法
3、SQL的书写顺序:select from join on where group by having order by
4、SQL的执行顺序:(1)from (2) join (3) on (4) where (5)group by(开始使用select中的别名,后面的语句中都可以使用)
(6) avg,sum… (7)having (8) select (9) distinct (10) order by
5、group by ,order by ,以及avg,sum等相关的函数用法