day28:mysql 分组、多表查询、作业

分组group by [having]

将结果集分组统计,规则:
出现了groub by的查询语句,select后⾯的字段只能是集合函数和group by后
⾯有的字段,不要跟其它字段;
对分组进⾏过滤,可以使⽤having
如:select uid, count(*) num from php_forum group by uid; #num是别名

存储引擎

可以使⽤show engines命令查看数据库引擎,各存储引擎比较:
在这里插入图片描述

  • innoDB是默认存储引擎,是惟一支持外键,事务,行锁的引擎.其增删改效率高
  • myisam查询速度快,不支持事务\外键,支持表锁.

子查询

⼦查询嵌⼊到其他查询语句中查询语句,⼦查询只能出现在from,where、
having中
⼦查询不要⽤select *,exists除外
一般不超过3个嵌套

select * from blog_article where cid in (
select cid from blog_category where name='⼼情'
);
select * from (select * from grade where sno='101') as tmp;#必须要有as 别名

=多表查询=

多表连接必须要有连接条件,否则结果没有意义
多表连接有两种写法:隐式(标准sql)和显式内连接

内连接:判等或判不等的连接.必须是满足条件才会查询出来,如学生表和成绩表之间的连接,必须是student.sno=grade.sno

隐式(标准sql)连接:连接条件写到where字句中

select a.username,b.name ,c.title
-> from bbs_user a,bbs_category b,bbs_forum c
-> where b.cid = c.cid and c.uid = a.uid;

显式内连接(inner join): inner可省略

select avg(degree) from student s inner join grade g on s.sno=g.sno where s.class=95033;

管道

  • 查询结果又是一张表,给其增一个别名aa
select aa.sname from (select s.*  from student s inner join grade g on s.sno=g.sno) aa;
  • 多表连接 第一个连接形成一个表,再join第三个表,如此类推:
select s.*  from student s inner join grade g on s.sno=g.sno join course c on c.cno=g.cno;

外连接:判等或判不等的连接.必须是满足条件才会查询出来,如学生表和成绩表之间的连接,必须是student.sno=grade.sno。左连接以join左边的表为主,每一条记录就匹配右表的所有记录,如果有符合条件的就显示,如果不符合条件则以null填充。

如查询所有学生的Sname、Cname和Degree列(分布在三个表中),如果不用外连接就只会查询满足条件的(如:同时在三个表中的学生)记录,用外连接则会将所有学生查出来,如果不满足条件,则用null填充。

select s.sname,c.cname,g.degree,c.cname from student s left outer join grade g on s.sno = g.sno left outer join course c on c.cno=g.cno;

表的⾃身连接

把表当成两个表进行连接

select * from student a join student b on a.sno=b.sno 

典型应用: 查区号
表结构如下:code是某地区邮编,pid是父级地区的邮编,如杭州下属若干个区,想查杭州所有区号,就可以采用自表连接,a.code=a.pid
在这里插入图片描述

select * from areainfo a,areainfo b where a.pid=b.code and
a.name='⻘河县';

集合操作union

  • 可以使⽤union将两个查询结果合并,mysql只⽀持并,不⽀持差和交
  • 两个结果集中字段数⼀样,对应字段类型兼容
  • ⾃动去除重复记录,不去除重复记录可以⽤union all
  • order by 放到最后

select * from student where class = ‘95031’
union all
select * from student where ssex=‘⼥’;

内部函数

  • 字符串函数
    在这里插入图片描述
  • ⽇期函数
    在这里插入图片描述
  • 数学函数
    在这里插入图片描述
  • 其他函数
    在这里插入图片描述
033sql练习题
一、已知有如下表,请用sql语句在mysql里建立相应的表

表1  学生表(student)
列名	意义	类型	约束
sno	学号	varchar(3)	主键
sname	姓名	varchar(4)	非空
ssex	性别	varchar(2)	
sbirthday	生日	datetime	
class	班级编号	varchar(5)	非空

表2 课程表(course)
列名	意义	类型	约束
cno	课程号	varchar(5)	主键
cname	课程名	varchar(10)	非空
tno	教师编号	varchar(10)	非空

表3 成绩表(grade)
列名	意义	类型	约束
sno	学号	varchar(3)	主键
cno	课程号	varchar(5)	主键
degree	分数	numeric(3)	非空

表4 教师表(teacher)
列名	意义	类型	约束
tno	教师编号	varchar(3)	主键
tname	教师姓名	varchar(10)	非空
tsex	性别	varchar(2)	
tbirthday	生日	datetime	
prof	职称	varchar(6)	非空
depart	系	varchar(10)	非空

表5  等级表(rank)
列名	意义	类型	约束
down	分数下届	numeric(3)	非空
up	分数上界	numeric(3)	非空
rank	级别	varchar(1)	主键

二、将如下数据插入到表里
INSERT INTO student (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (108 ,'曾华' ,'男' , '1977-09-01',95033);
INSERT INTO student (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (105 ,'匡明' ,'男' , '1975-10-02',95031);
INSERT INTO student (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (107 ,'王丽' ,'女' , '1976-01-23',95033);
INSERT INTO student (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (101 ,'李军' ,'男' , '1976-02-20',95033);
INSERT INTO student (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (109 ,'王芳' ,'女' , '1975-02-10',95031);
INSERT INTO student (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (103 ,'陆君' ,'男' , '1974-06-03',95031);

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

INSERT INTO grade(SNO,CNO,DEGREE)VALUES ('103','3-245',86);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (105,'3-245',75);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (109,'3-245',68);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (103,'3-105',92);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (105,'3-105',88);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (109,'3-105',76);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (101,'3-105',64);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (107,'3-105',91);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (108,'3-105',78);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (101,'6-166',85);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (107,'6-106',79);
INSERT INTO grade(SNO,CNO,DEGREE)VALUES (108,'6-166',81);

INSERT INTO teacher(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) 
VALUES (804,'李诚','男','1958-12-02','副教授','计算机系');
INSERT INTO teacher(TNO,TNAME,TSEX,TBIRTHDAY,PRO,DEPART) 
VALUES (856,'张旭','男','1969-03-12','讲师','电子工程系');
INSERT INTO teacher(TNO,TNAME,TSEX,TBIRTHDAY,PRO,DEPART)
VALUES (825,'王萍','女','1972-05-05','助教','计算机系');
INSERT INTO teacher(TNO,TNAME,TSEX,TBIRTHDAY,PRO,DEPART) 
VALUES (831,'刘冰','女','1977-08-14','助教','电子工程系');


insert into ranks(down,up,ranks) values(90,100,'A');
insert into ranks(down,up,ranks) values(80,89,'B');
insert into ranks(down,up,ranks) values(70,79,'C');
insert into ranks(down,up,ranks) values(60,69,'D');
insert into ranks(down,up,ranks) values(0,59,'E');


三、sql语句练习
1、 查询Student表中的所有记录的Sname、Ssex和Class列。
select sno,sname,class from student;

2、 查询教师所有的单位即不重复的Depart列。
select distinct depart from teacher ;

3、 查询Student表的所有记录。
select * from student;

4、 查询Grade表中成绩在6080之间的所有记录。
select * from grade where degree between 60 and 80;

5、 查询Grade表中成绩为858688的记录。
select * from grade where degree in (85,86,88);

6、 查询Student表中“95031”班或性别为“女”的同学记录。
select * from student where class="95031" or ssex="女";

7、 以Class降序查询Student表的所有记录。
select * from student order by class desc;
8、 以Cno升序、Degree降序查询Grade表的所有记录。
select * from grade order by cno,degree desc;
9、 查询“95031”班的学生人数。
select count(*) from student where class=95031;
10、查询Grade表中的最高分的学生学号和课程号。 
不能直接如下查询,因为max(degree)只有一行,sno,cno有多行
select max(degree),sno,cno from grade; 
要这样:
select cno,sno from grade where degree = (select max(degree) from grade);
11、查询‘3-105’号课程的平均分。
select avg(degree) from grade where cno="3-105";
可以增加“as 平均分”
select cno,avg(degree) as 平均分 from grade where cno="3-105";
12、查询Grade表中至少有5名学生选修的并以3开头的课程的平均分数。
select *, count(*) from grade group by cno having count(*)>=5 and cno like "3%";
先用where再用group byhavingselect cno,avg(degree) as 平均分 from grade where cno like "3%" group by cno having count(cno)>=5;

13、查询最低分大于70,最高分小于90的Sno列。
select sno,degree from grade where degree between 70 and 90;
14、查询所有学生的Sname、Cno和Degree列。
select s.sno,s.sname,g.degree from student s,grade g where s.sno = g.sno;

15、查询所有学生的Sno、Cname和Degree列。(使用内连接不能显示没选课学生)
内连接显示两个记录(记录必须同时满足在学生表、课程表和成绩表):select student.sno,sname,cname,degree from student,course,grade where student.sno=grade.sno and grade.cno=course.cno;
左外连接显示所有学生:select s.sno,s.sname,g.degree,c.cname from student s left outer join grade g on s.sno = g.sno left outer join course c on c.cno=g.cno;
16、查询所有学生的Sname、Cname和Degree列。
select s.sname,c.cname,g.degree from student s left outer join grade g on s.sno = g.sno left outer join course c on c.cno=g.cno;

17、查询“95033”班所选课程的平均分。
select avg(degree) from student s inner join grade g on s.sno=g.sno where s.class=95033;

---以下题目均需提供两种sql语句
18、查询选修课成绩为A等的学生信息
select s.sname from student s, grade g where g.sno=s.sno and g.degree>=(select down from ranks where ranks="A");
select s.sname from student s inner join  grade g on g.sno=s.sno where g.degree>=(select down from ranks where ranks="A"); 
19、查询选修“3-105”课程的成绩高于“109”号同学成绩的所有同学的记录。
select s.sname ,g.degree,g.cno from student s, grade g where s.sno=g.sno and cno="3-105" and degree>(select degree from grade where sno=109 and cno="3-105");

select s.sname ,g.degree,g.cno from student s inner join grade g on s.sno=g.sno and cno="3-105" and degree>(select degree from grade where sno=109 and cno="3-105");
20、查询grade中选学一门以上课程的同学中分数为非最高分成绩的记录。
select * from grade where (cno,degree) not in (select cno,max(degree)from grade group by cno ) and sno in (select sno from grade group by sno having count(sno)>1);
此颜色部分是查询选学了一门以上的同学学号
红颜色部分是查询各科最高分的课程号和分数
最后满足条件的同学是:不在红色部分但在蓝色部分。
select * from grade where (cno,degree) not in (select cno,max(degree)from grade group by cno) and sno in (select sno from grade group by sno having count(sno)>1);
21、查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录。
select *  from grade where degree >(select degree from grade where sno=109 and cno="3-105");
22、查询和学号为108的同学同年出生的所有学生的Sno、Sname和Sbirthday列。
select * from student where year(sbirthday)=(select year(sbirthday) from student where sno=108)
23、查询“张旭“教师任课的学生成绩。
select * from grade where cno=(select cno from course where tno=(select tno from teacher where tname="张旭"));
24、查询选修某课程的同学人数多于5人的教师姓名。
select tname from teacher where tno = (select tno from course where cno = (select cno from (select cno,count(cno) c from grade group by cno) b where b.c>5));
25、查询95033班和95031班全体学生的记录。
select * from student where class in (95033,95031);
26、查询存在有85分以上成绩的课程Cno.
select cno from grade where degree >85;
27、查询出“计算机系“教师所教课程的成绩表。
select * from grade where cno=(select cno from course c  inner join (select tno from teacher where depart="计算机系") t on  c.tno = t.tno);
28、查询“计算机系”与“电子工程系“不同职称的教师的Tname和Prof。
select tname,pro from teacher where pro in (select pro from teacher where depart="电子工程系" or depart="计算机系" group by pro);

29、查询选修编号为“3-105“课程且成绩至少高于选修编号为“3-245”的同学的Cno、Sno和Degree,并按Degree从高到低次序排序。
select * from grade where cno='3-245' and degree>(select min(degree) from grade where cno="3-245") order by degree desc;

30、查询选修编号为“3-105”且成绩高于选修编号为“3-245”课程的同学的Cno、Sno和Degree.
select * from grade where cno="3-105" and degree>(select max(degree) from grade where cno="3-245");
31、查询所有教师和同学的name、sex和birthday.
select tname,tsex,tbirthday from teacher union select sname,ssex,sbirthday from student;
32、查询所有“女”教师和“女”同学的name、sex和birthday.
select tname,tsex,tbirthday from teacher where tsex="女" union select sname,ssex,sbirthday from student where ssex="女";
33、查询成绩比该课程平均成绩低的同学的成绩表。(内连接可矣)
step 1:create view avg(cno,avg) as select cno,avg(degree) as avg from grade group by cno;
step 2:select a.sno,a.cno,a.degree from grade a join avg b on a.cno=b.cno and a.degree where a.degree<b.avg;
(step 2 also: 
select a.sno,a.cno,a.degree from grade a ,avg b where a.cno=b.cno and a.degree>b.avg;)

34、查询所有任课教师的Tname和Depart.
select a.tno,b.tname,b.depart from (select tno from teacher union select tno from course) as a left join teacher as b on a.tno=b.tno;
任课老师除了Teacher表还在course里有一个,但无信息,因此用左连接所有老师列出,即使没有姓名信息和系信息,直接用null填充.
35  查询所有未讲课的教师的Tname和Depart. 
select tno,tname,depart  from teacher  where tno not in (select tno from course);
36、查询至少有2名男生的班号。
select class  from student where ssex="男" group by class having count(class)>1;(where在前面)
37、查询Student表中不姓“王”的同学记录。
select * from student where sname not like "王%";
38、查询Student表中每个学生的姓名和年龄。
select sname,year(now())-year(sbirthday)from student;
39、查询Student表中最大和最小的Sbirthday日期值。
select max(sbirthday) min,min(sbirthday) max from student;

40、以班号和年龄从大到小的顺序查询Student表中的全部记录。
select * from student order by class desc,sbirthday asc;
41、查询“男”教师及其所上的课程。
select * from teacher,course where teacher.tsex="男" and teacher.tno=course.tno;
42、查询最高分同学的Sno、Cno和Degree列。
select sno,cno,degree from grade where degree = (select max(degree) from grade);
43、查询和“李军”同性别的所有同学的Sname.
select sname from student where (ssex ,class)=(select ssex,class from student where sname="李军");
44、查询和“李军”同性别并同班的同学Sname.
select sname from student where (ssex ,class)=(select ssex,class from student where sname="李军") and sname !="李军";
45、查询所有选修“计算机导论”课程的“男”同学的成绩表
select g.sno,s.sname,g.degree from grade g,student s where cno=(select cno from course where cname="数据电路") and g.sno=s.sno and s.ssex="男";

46、查询计算机系教师所教课程成绩为B等的课程信息
select degree from  grade where cno in (select cno from teacher t,course c where t.depart="计算机系" and t.tno=c.tno) and degree between (select down from ranks where ranks="B") and (select up from ranks where ranks="B");

47、查询成绩在C等以上的学生的所在班级
select distinct class from (select * from grade where degree >=(select down from ranks where ranks="C"))

48、查询班里B等以上学生人数最多的班级信息



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值