准备数据,倒入sql文件
运行sql文件 得到四张表
select * from 表名 * 代表全部
1、AS子句作为别名
select studentname as "姓名" , sex as "性别",gradeid as "班级ID" from student;
多表查询给表起别名 简化代码
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190817223436535-419977040.png)
2、distinct 去重
DISTINCT关键字
作用:
去掉SELECT查询返回的记录结果中重复的记录(所有返回列的值都相同),只返回一条
语法:
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190817223821376-2130146500.png)
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190817224343870-1969362237.png)
多条语句去重
select distinct ID,NAME from student;
以 ID和NAME 为单位
例如:如下不算重复
1 aa
1 bb
3、where条件语句
4、LIKE模糊查询
查询姓李的同学记录
% 所有字符
select * from student where StudentName like "李%";
"_" 代表一个字符
查询姓李X(名只有1个)的同学记录
select * from student where StudentName like "李_";
查询名字中包含文的记录
select * from student where StudentName like "%文%";
查询以 姓名 明 结尾的纪录
select * from student where StudentName like "%明"
查询所有姓 李 的学生所有成绩
select s.StudentNo as "'李'同学学号",r.stuResult as "'李'同学成绩" from student as s ,result as r
where s.StudentNo=r.StudentNo AND s.StudentName like "李%";
查询 Java的考试成绩
select s.subjectName as java,r.stuResult as "java的成绩" from subject as s ,result as r
where s.SubjectName="java" and s.SubjectNo=r.SubjectNo;
查询考试JAVA的学生的学号和考试成绩
select r.StudentNo as "学号",r.stuResult AS "考试成绩" from result as r ,subject as s
where r.subjectNo=s.subjectNo and s.subjectName="java";
查询考试Java的学生学号,姓名,考试成绩
select r.StudentNo as "学号",st.StudentName as "姓名",r.stuResult AS "考试成绩"
from result as r ,subject as s,student as st where
r.subjectNo=s.subjectNo AND
r.StudentNo=st.StudentNo and
s.subjectName="java";
5 查询Student表中年龄为12或性别为“女”的同学记录。
CURDATE() 函数返回当前的日期。
select * from student where TIMESTAMPDIFF(YEAR,BornDate,CURDATE())=12 or Sex=0;
year(now())-year(BronDate)
TIMESTAMPDIFF函数,有参数设置,
可以精确到天(DAY)、小时(HOUR),分钟(MINUTE)和秒(SECOND),
。对于比较的两个时间,时间小的放在前面,时间大的放在后面。
5、联合查询
SELECT 字段列表
FROM 表1 INNER|LEFT|RIGHT JOIN 表2
ON 表1.字段 = 表2.字段;
要求:从subject和grade数据表查询课程名称和所属年级名称
select s.subjectName as "课程名称" ,g.gradeName as "年级名称" from subject as s INNER JOIN grade as g
on s.gradeid=g.gradeID;
JION左边的是左表 JOIN JOIN右边的是右表
6、order by排序
查询所有考试结果,并按成绩由高到低排列 ORDRY BY 字段 select * from result ORDER BY stuResult desc;
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190818182036020-1247416358.png)
根据成绩升序排序,当成绩相同时根据学号降序排序
主要排序和次要排序
select * from result ORDER BY stuResult asc ,StudentNo DESC ;
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190818183249235-1569260293.png)
7、LIMIT 分页查询
m对应索引,n是步长
select * from result limit 1,5;
查询起始为学号为1002 共5条记录
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190818183946537-43350899.png)
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190818184111934-491384718.png)
8、统计函数
count计数、sum求和、avg平均值、max最大值、最小值
SELECT count(*) from student;
count可以不放字段名,其他的都要放字段
9、group by 分组
按照不同的课程分组,分别算出其平均分、最高分和最低分,对于
平均分低于60分的不予显示
select s.subjectName as "课程名" ,avg(r.stuResult) as "平均分",MAX(r.stuResult) "最高分",MIN(r.stuResult) "最低分"
from subject s, result r where s.SubjectNo=r.SubjectNo GROUP BY r.SubjectNo HAVING avg(r.stuResult)>60;
10、having
普通等值写法
select subjectName,avg(stuResult),max(stuResult),min(stuResult) from subject s,result r WHERE s.subjectNo=r.subjectNO GROUP BY r.subjectno HAVING avg(stuResult)>60;
select subjectname,avg(stuResult),max(stuResult),min(stuResult) from subject s
INNER JOIN result r
on r.subjectno=s.subjectno
GROUP BY r.subjectno
having avg(stuResult)>60;
11、子查询
查询大二的上了什么课?
select subjectName from subject where gradeid =
(select gradeID from grade where gradeName="大二");
查询 课程为java且分数不小于80分的学生的学号和姓名?
gradeid是桥梁
子查询方法:
SELECT StudentNo,StudentName from student where StudentNo in
(select StudentNo from result where SubjectNo in
(select subjectNo FROM subject where subjectName="java") and stuResult>=80
);
连表查询方法:
select st.StudentNo,StudentName from student as st
INNER JOIN
result as r on st.StudentNo=r.StudentNo
INNER JOIN subject as s ON
r.SubjectNo=s.subjectNo where s.subjectName="java" and r.stuResult>=80;
等值连接
select s.studentno,studentname from student s,subject su,result r
WHERE r.studentno=s.studentno
and su.subjectno=r.subjectno
and subjectname='java'
and stuResult>80;
sql语句注意事项
(1)MYSQL 查询语句 不区分大小写
例如:
select * from table where name = "aa"
select *from table where name = "AA"
这两条的查询结果是一样的
(2)sql count(*) 和 count(col)、count(1)区别
row行,col列
count(*)和count(列)根本就是不等价的,count(*)是针对于全表的,而count(列)是针对于某一列的,如果此列值为空的话,count(列)是不会统计这一行的。
也就是说count(列)会用到索引,并且会过滤掉该列为null的那行。
而count(*)是全表扫描,并且只要某一条数据有一列不为null,那就会统计到这条数据。
count(1)可以理解为表里有一列数据都为1的列。
count(*),执行时会把星号翻译成字段的具体名字,效果也是一样的,不过多了一个翻译的动作,比固定值的方式效率稍微低一些。
group_concat 和 group by 是一起使用的
综合练习
course sc student teacher course:Cid,Cname,Tid sc:Id,Sid,Cid,score student:Sid,Sname,Sage,Sex teacher:Tid,Tname 1查询每门课程被选修的人数 select Cid,count(Sid) "人数" from sc GROUP BY Cid; select Cid,count(*) "人数" from sc GROUP BY Cid; 2 查询只选修了4门课程的学生学号,和姓名 SELECT s.Sid,s.Sname from student s INNER JOIN sc on sc.Sid=s.Sid GROUP BY sc.Sid HAVING count(sc.Cid)=4; select s.sid,sname from student s INNER JOIN sc on s.Sid=sc.Sid GROUP BY s.Sid HAVING count(*)=4; 3 查询姓张的学生名单 select Sname from student where Sname like "李%"; 4 查询同名同姓的学生名单,显示姓名,同名的人数 select Sname,count(Sid) "人数" from student GROUP BY Sname HAVING count(Sid)>=2; select sname,count(*) from student GROUP BY sname having count(*)>=2; 5 查询每门课程的平均成绩,按照平均成绩升序,平均成绩相同时按课程号降序; select Cname "课程名",avg(score) "平均成绩" from course c INNER JOIN sc on c.Cid=sc.Cid GROUP BY c.Cid ORDER BY avg(score),c.Cid desc; select cid,avg(score) FROM sc GROUP BY cid ORDER BY avg(score) asc,cid desc; 6 查询平均成绩大于80分的学生的学号,姓名和平均成绩 select s.Sid "学号",Sname "姓名",avg(score) "平均成绩" from student s INNER JOIN sc ON s.Sid=sc.Sid GROUP BY s.Sid HAVING avg(score)>80; select s.sid,sname,avg(score) 'avg' FROM sc INNER JOIN student s on s.sid=sc.sid GROUP BY s.sid HAVING avg>80; 7 查询 所有 的课程分数都低于80分的学生的姓名 ???????已解决 是所有的!!! select Sname "姓名" from student s INNER JOIN sc ON s.Sid = sc.Sid GROUP BY s.Sid HAVING MAX(score)<80; select sname from sc INNER JOIN student s on s.sid=sc.Sid GROUP BY s.Sid HAVING max(score)<80; 8 查询所有同学的选课情况,显示学生的姓名和选修的课程名 select Sname "姓名",Cname "课程名" from student s INNER JOIN sc ON s.Sid=sc.Sid INNER JOIN course c ON c.Cid=sc.Cid ORDER BY s.Sid; 下面这种更好: select sname,group_concat(cname) from student s INNER JOIN sc on s.sid=sc.sid INNER JOIN course c on c.cid=sc.cid GROUP BY s.sid
group_concat 和 group by 是一起使用的
9 查询学习Java的学生人数。 select count(Sid) "学习java人数" from sc INNER JOIN course on course.Cid=sc.Cid WHERE course.Cname="java"; select count(*) from sc INNER JOIN course c on sc.cid=c.cid WHERE cname='java'; 10查询sc表中的最高分的学生学号和课程号。(子查询或者排序) select s.Sid "最高分学号",sc.Cid "课程号" from student s INNER JOIN sc ON s.Sid=sc.Sid WHERE score = (SELECT MAX(score) from sc); select sid,cid,score from sc ORDER BY score DESC limit 1; 11 查询成绩在80-90之间的学生学号 更正去重 SELECT DISTINCT Sid from sc WHERE score BETWEEN 80 AND 90; 12 查询成绩在80-90之间的学生的姓名 更正去重 SELECT DISTINCT Sname "学生姓名" from student INNER JOIN sc on student.Sid=sc.Sid WHERE score BETWEEN 80 AND 90; SELECT DISTINCT sname from student s INNER JOIN sc on s.sid=sc.sid WHERE score BETWEEN 80 and 90; 13 查询每个学生的平均成绩 select Sname "学生姓名",avg(score) "平均成绩" from student s INNER JOIN sc ON s.Sid=sc.Sid GROUP BY sc.Sid; 14 查询所有任课老师的姓名和课程名 select Tname "老师姓名",Cname "课程名" from teacher t INNER JOIN course c on t.Tid=c.Tid; 下面的方法更好: select tname,group_concat(cname) from teacher t INNER JOIN course c on c.tid=t.tid GROUP BY t.tid; 15 查询最高分的学生学号,学生姓名,考试成绩 错误: select s.Sid "学号",Sname "学生姓名",score "考试成绩" from student s INNER JOIN sc on s.Sid=sc.Sid where score = (SELECT MAX(score) from sc);
更正: select sname,s.sid,score from sc INNER JOIN student s on s.sid=sc.sid WHERE s.sid=( select sid from sc WHERE score=(select max(score) from sc) );
select sname,s.sid,GROUP_CONCAT(score) from sc INNER JOIN student s on s.sid=sc.sid WHERE s.sid=( select sid from sc WHERE score=(select max(score) from sc) ) GROUP BY s.sid;
练习题2,重点
course:cid,cname,tid
sc:sid,cid,score
student:sid,sname,age,sex
teacher:tid,tname
select * from course;
select * from sc;
select * from student;
select * from teacher;
1.查询平均成绩大于60分的同学的学号和平均成绩???? 要分组
where只能用于存在的列 错误表达: WHERE AVG(score)>60;
select s.sid,avg(score) from student s INNER JOIN sc
on s.sid=sc.sid HAVING group by s.sid avg(score)>60;
2.查询所有同学的学号、姓名、选课数、总成绩
select s.sid "学号",sname "姓名",count(cid) "选课数",sum(score)"总成绩"
from student s INNER JOIN sc on s.sid=sc.sid GROUP BY sc.sid
3. 查询姓“李”的老师的个数
select count(*)"姓李老师个数" from teacher where tname LIKE "李%";
5.查询学过“李纯”老师课的同学的学号、姓名
select s.sid"学号",sname"姓名" from student s INNER JOIN sc ON
s.sid=sc.sid INNER JOIN course as c on c.cid=sc.cid INNER JOIN
teacher t on c.tid = t.tid WHERE tname = "李纯";
6.查询没学过“李雷”老师课的同学的学号、姓名?????????---已解决
select sid,sname from student where sid not in (
select sid from sc where cid in(
select cid from course where tid =(
select tid from teacher where tname="李雷")));
7.查询“001”课程比“002”课程成绩高的所有学生的学号、姓名?????? --已解决---
course:cid,cname,tid
sc:sid,cid,score
student:sid,sname,age,sex
teacher:tid,tname
法一:
select sid,sname from student where sid in(
SELECT t1.sid FROM sc t1, sc t2
WHERE
t1.sid=t2.sid and
t1.cid = '001' AND
t2.cid = '002' AND
t1.score > t2.score);
法二:
select s.sid,sname from student s
INNER JOIN sc a on s.sid=a.sid INNER JOIN sc b
on a.sid=b.sid
where
a.cid = '001' AND
b.cid = '002' AND
a.score > b.score;
8. 查询学过“001”并且也学过编号“003”课程的同学的学号、姓名
select s.sid"学号",sname"姓名" from student s INNER JOIN sc a ON
s.sid =a.sid INNER JOIN sc b on a.sid=b.sid
WHERE a.cid="001" and b.cid="003" GROUP BY b.sid;
9.查询各科成绩最高分和最低分:以如下形式显示:课程ID,课程名,最高分,最低分
select c.cid"课程ID",cname"课程名",max(score)"最高分",min(score)"最低分" FROM
course c INNER JOIN sc on c.cid=sc.cid GROUP BY sc.cid;
10. 查询没有学全所有课的同学的学号、姓名
select s.sid"学号",sname"姓名" from student s INNER JOIN sc ON
s.sid =sc.sid GROUP BY sc.sid HAVING count(*)<(select count(*) from course);
11.查询学过“李雷”老师所教的所有课的同学的学号、姓名???----已解决
course:cid,cname,tid
sc:sid,cid,score
student:sid,sname,age,sex
teacher:tid,tname
select sid"学号",sname"姓名" from student where sid in (
select sid from sc where cid in (
SELECT cid from course where tid=
(select tid from teacher where tname="李雷")));
12. 查询至少学过学号为“1001”同学所学的一门课的其他同学学号和姓名
方法一:
要排除学号为"1001"的学号
select DISTINCT s.sid"学号",sname"姓名" from student s INNER JOIN sc ON
s.sid=sc.sid where cid in
(select cid from sc where sid = "1001") and s.sid<>"1001";
方法三:
select sid"学号",sname"姓名" from student WHERE sid in
(select DISTINCT sid from sc where cid in
(select cid from sc where sid = "1001")and sid<>"1001");
13.按各科平均成绩从低到高和及格率的百分数从高到低顺序排序???????---已解决
select cid,round(avg(score),2)t1,(sum(
case when score BETWEEN 60 and 100 then
1
ELSE
0
end)/count(*))*100 t2
from sc GROUP BY cid ORDER BY t1,t2 desc;
select cid,round(avg(score),2)t1,CONCAT(round((sum(
case when score BETWEEN 60 and 100 then
1
ELSE
0
end)/count(*))*100),'%') t2
from sc GROUP BY cid ORDER BY t1,t2 desc;
![](https://img2018.cnblogs.com/blog/1447456/201908/1447456-20190825193209350-1263829465.png)
14.删除学习“李纯”老师课的SC表记录
DELETE from sc where cid in (
SELECT cid from course where tid=
(select tid from teacher where tname="李纯"));
练习题三
select * from course;
select * from sc;
select * from student;
select * from teacher;
course:cid,cname,tid
sc:sid,cid,score
student:sid,sname,age,sex
teacher:tid,tname
1 查询任何一门课程成绩在70分以上的姓名、课程名和分数
select sname,GROUP_CONCAT(cname),GROUP_CONCAT(score) from student s INNER JOIN sc ON
s.sid=sc.sid INNER JOIN course c on c.cid=sc.cid GROUP BY sc.sid HAVING min(sc.score)>70;
2 查询所有不及格的课程,并按课程号从大到小罗列课程ID和学生ID
select cid,GROUP_CONCAT(s.sid) from sc INNER JOIN student s on sc.sid=s.sid
where score<60 GROUP BY cid ORDER BY cid desc;
3 查询课程编号为003且课程成绩在80分以上的学生的学号和姓名
select s.sid,sname from student s INNER JOIN sc on s.sid=sc.sid
WHERE cid='003' and score>80;
4 求选全了课程的学生人数
select count(a.sid) from
(select sid from sc
GROUP BY sid HAVING COUNT(*)=
(select count(*) from course)) a;
5 查询选修李 老师所授课程的学生中,成绩最高的学生姓名及其成绩
select sname,max(score) from student s ,teacher t,course c,sc
where t.tid=c.tid and
tname like "李%" AND
c.cid=sc.cid AND
sc.sid=s.sid
GROUP BY tname;
6 查询各个课程及相应的选修人数
select c.cid,count(*) from course c INNER JOIN sc ON
c.cid=sc.cid GROUP BY sc.cid;
7 查询不同课程成绩相同的学生的学号、课程号、学生成绩?????
select s1.sid,s2.sid,sc1.cid,sc1.score,sc2.score from student s1,student s2,sc sc1,sc sc2
where s1.sid!=s2.sid and s1.sid=sc1.sid and s2.sid=sc2.sid and sc1.cid!=sc2.cid and sc1.score=sc2.score;
8 检索至少选修两门课程的学生学号
select sid from sc GROUP BY sid HAVING count(*)>=2;
9 查询全部学生都选修的课程的课程号和课程名
哪一个课程被所有学生多选?
select c.cid,cname from course c INNER JOIN sc ON
c.cid=sc.cid GROUP BY sc.cid HAVING count(*)=(select count(*) from student);
4 求选全了课程的学生人数????
select count(*) from
(select sid from sc GROUP BY sid HAVING
count(*)=(select count(*) from course)) a;
2 查询sc表里 所有 不及格的课程,并按照课程号从大到小罗列课程id和学生id?????
select sid,cid,score from sc where score<60 ORDER BY sid desc,cid desc;
练习四
导入cdsgusTable表
select * from cdsgustable;
id
cname
CtfTp
CtfId
Gender
Birthday
Address
Zip
Mobile
Tel
Fax
EMail
Version
1. 获取每个性别的人数
select gender,count(*) from cdsgustable GROUP BY gender;
2. 查询2012年的数据
select * from cdsgustable where year(version)=2012;
3. 查询2012年12月的数据
select * from cdsgustable where year(version)=2012 and month(version)=12;
4. 查询姓王的人数
select count(*)'姓王的人数' from cdsgustable where cname like '王%'
5. 查询姓李的,并且CTFTP不是OTH的人数
select count(*) from cdsgustable where cname like '李%' and CtfTp<>'OTH';
6. 查询现在年龄大于30岁的人数
select count(a.cname) from
(select cname from cdsgustable where (year(NOW())-year(Birthday))>30 GROUP BY cname) a;
错误:select count(*) from cdsgustable where (year(NOW())-year(Birthday))>30;
7. 根据出生年月日,转换为星期,现实出生人最多的那个星期几的英语单词
DATE_FORMAT(NOW(),"%W")
select DATE_FORMAT(Birthday,"%W") bir_week from cdsgustable GROUP BY bir_week HAVING count(*)=
(select count(*) from cdsgustable GROUP BY DATE_FORMAT(Birthday,"%W") limit 1);
附加题9:获取每年的男女性别所占的百分比,并保留两位小数(结果如下所示)
提示:保留几位小数用函数round(值,保留小数位数)
select year(Birthday) year,CONCAT(round((sum(
case when Gender='F' then
1
ELSE
0
end)/count(Gender))*100,2),'%')'女',CONCAT(round((sum(
case when Gender='M' then
1
ELSE
0
end)/count(Gender))*100,2),'%')'男'
from cdsgustable GROUP BY year;
select * from course; select * from sc; select * from student; select * from teacher; course:cid,cname,tid sc:Id,Sid,Cid,score student:Sid,Sname,Sage,Sex teacher:Tid,Tname 1. 查询不同课程成绩相同的学生的学号、课程号、学生成绩 select s1.sid,s1.cid,s2.sid,s2.cid,s1.score from sc s1 INNER JOIN sc s2 on s1.cid<>s2.cid where s1.score=s2.score; 2. 统计各科成绩的各分数段人数:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60] select sc.cid,cname, sum(case when score between 85 and 100 then 1 ELSE 0 end)'[100-85]', sum(case when score between 70 and 85 then 1 ELSE 0 end)'[85-70]', sum(case when score between 60 and 70 then 1 ELSE 0 end)'[70-60]', sum(case when score <60 then 1 ELSE 0 end)'[ <60] ' from sc INNER JOIN course c on c.cid=sc.cid GROUP BY sc.cid; 3. 查询所有学生的选课情况,显示学生姓名和选修的课程名 select sname,GROUP_CONCAT(cname)from student s INNER JOIN sc ON s.sid=sc.sid INNER JOIN course c on sc.cid=c.cid GROUP BY sc.sid; 4. 把sc表中李浩然老师教课的成绩都改为此课程的平均成绩 ????