数据库常用语句以如下需求展开:
一、建库
CREATE DATABASE [dbname] DEFAULT CHARSET utf8 COLLATE utf8_general_ci; 例: CREATE DATABASE test DEFAULT CHARSET utf8 COLLATE utf8_general_ci; --创建test数据库
二、建表
CREATE TABLE [tbname](字段 约束,字段 约束); create table test.class( cid int auto_increment, caption varchar(10) not null , primary key (cid)); --创建班级表 create table test.teacher(tid int auto_increment,tname varchar(10),primary key (tid)); --创建老师表 create table test.student(sid int auto_increment,sname varchar(10) not null,gender varchar(2) default '男' check (gender in ('男','女')), class_id int not null, primary key (sid), foreign key (class_id) references class(cid) ); -- 创建学生表
create table test.lesson( lid int auto_increment,lname varchar (10) not null , teacher_id int not null , primary key (lid), foreign key (teacher_id) references teacher(tid) ); --创建课程表
create table test.mark( mid int auto_increment, student_id int not null , lesson_id int not null , point int not null , primary key (mid), foreign key (student_id) references student(sid), foreign key (lesson_id) references lesson(lid) ); --创建成绩表
三、插入数据
--插入班级数据 insert into class values (1,'三年二班'), (2,'一年三班'), (3,'三年一班'), (4,'二年二班');
--插入老师数据 insert into teacher values (1,'波多'), (2,'苍空'), (3,'饭岛'), (4,'小泽');
--插入学生数据 insert into student values (1,'钢蛋','女',1), (2,'铁锤','女',1), (3,'山炮','男',3), (4,'王美丽','男',2), (5,'张三','女',1), (6,'李四','男',2), (7,'王五','女',2), (8,'赵六','男',3), (9,'犀利哥','男',1), (10,'芙蓉姐','女',3);
--插入课程数据 insert into lesson values (1,'生物',1), (2,'体育',2), (3,'物理',3), (4,'语文',4);
--插入成绩数据 insert into mark values (1,1,1,28), (2,2,2,50), (3,3,3,79), (4,4,4,100), (5,5,2,25), (6,6,1,54), (7,7,3,68), (8,8,4,75), (9,9,4,76), (10,10,1,89), (11,8,3,94), (12,6,2,97), (13,2,1,99), (14,5,2,38), (15,7,4,59);
四、基础操作
4.1 查询“生物”课程比“体育”课程成绩高的所有学生的学号:
求解思路:学生表和成绩表关联,课程表和成绩表关联,三张表关联起来就可以得到学生对应课程的成绩,给定条件课程分别为“生物”和“体育”,过滤出两个条件后再将两张表关联查询及可得出符合条件的学生。
select A.sid from ( select S.sid,S.sname,L.lname,M.point from student S,mark M, lesson L where S.sid=M.student_id and L.lid=M.lesson_id and L.lname= "生物" ) A,( select S.sid,S.sname,L.lname,M.point from student S,mark M, lesson L where S.sid=M.student_id and L.lid=M.lesson_id and L.lname= "体育" ) B where A.sid=B.sid and A.point>B.point --写法一
select A.sid from ( select S.sid,M.point from student S LEFT JOIN mark M on S.sid=M.student_id LEFT JOIN lesson L on M.lesson_id=L.lid where L.lname= "生物" ) A LEFT JOIN ( select S.sid,M.point from student S LEFT JOIN mark M on S.sid=M.student_id LEFT JOIN lesson L on M.lesson_id=L.lid where L.lname= "体育" ) B on A.sid=B.sid where A.point > B.point --写法二
4.2 查询平均成绩大于60分的同学的学号和平均成绩:
求解思路:分数在mark表,学生ID 在student表和mrke 表中都存在,条件信息在mark 表中全部满足,所以只需要查询一张表;结果需求为平均成绩大于60分的同学平均成绩,如果一个学生有多个选课,可以给同一个学生求平均值,如果一个学生只选修一门课程,则分数就是平均值。所以需要对学生分组,然后对分组后的结果求平均值,并过滤出大于60分的。
select * from ( select student_id as sid, avg (point) as point from mark group by (student_id)) A where A.point > 60 ;
4.3 查询所有同学的学号、姓名、选课数、总成绩:
求解思路:学号在mark表和student 表中都存在,姓名在student 表,选课在mark表中,总成绩是point 的sum值也只依赖mark 表。所以只需要关联student表和mark表即可查出学生的学号、姓名、选棵数和总成绩。
select S.sid,S.sname, SUM (M.point) from student S,mark M where S.sid=M.student_id group by (S.sid);
4.4 查询姓“小”字开头的老师名字个数:
求解思路:老师名字在teacher 表中,按照小字开头匹配后,做统计即可
select count (*) from teacher where tname like "小%" ;
4.5 查询没学过“波多”老师课的同学的学号、姓名:
求解思路:老师名在teacher表中,选修波多老师的课的学号在mark 表中,姓名在student表中,但mark 表中与老师没有关联关系,因为选课对应的老师在lesson表中,所以要以学生为维度 关联4张基本表查询。
select S.sid,S.sname from ( select * from ( select * from teacher T,lesson L where T.tname= "波多" and L.teacher_id=T.tid) TL, mark M where TL.lid = M.lesson_id) as TLM, student S where TLM.student_id = S.sid;
4.6 查询课程编号“2”的成绩比课程编号“1”成绩低的所有同学的学号、姓名:
求解思路:成绩、学号和课程编号都在mark表中,学号和姓名在学生表中。所以需要关联两张表查询。
select A.sid,A.sname from ( select S.sid,S.sname,M.point from mark M,student S where S.sid=M.student_id and M.lesson_id=2) A,( select S.sid,S.sname,M.point from mark M,student S where S.sid=M.student_id and M.lesson_id=1) B where A.sid=B.sid and A.point < B.point
4.7 查询有课程成绩小于60分的同学的学号、姓名:
求解思路:成绩和学号在mark表, 学号和姓名在student 表,所以关联两张表查询即可。
select S.sid,S.sname from mark M, student S where M.student_id = S.sid and M.point >60 ORDER BY (sid);
4.8 查询没有学全所有课的同学的学号、姓名:
求解思路:所有课程在lesson 表中,学号和学习课程在mark表中,学号和姓名在student表中。所以,先连接student表和mark表得到所有学生学习的所有课程,然后按学生做分组,得到每个学生学习的课程数,再用学习的课程数与lesson中所有课程数对比,小于所有课程就是没有学全的学生。
select SM.sid,SM.sname from (select S.sid,S.sname,count(lesson_id) as smcnum from student S,mark M where S.sid=M.student_id group by (S.sid)) SM, (select count(*) as lcnum from lesson) L where SM.smcnum < L.lcnum;
4.9 查询至少有一门课与学号为“2”的同学所学相同的同学的学号和姓名:
求解思路:学号与课程在mark表中,学号与姓名在student表中。首先与两张表有关联,学号为“1”的学生学习了几门课,可以在mark中得到。mark 中其他同学只要选课中包含"2" 的课程及可关联student 得到学号和姓名。
select SM.sid,SM.sname from ( select S.sid,S.sname,M.lesson_id from mark M,student S where M.student_id = S.sid) SM WHERE SM.lesson_id in ( select lid from mark M,lesson L where M.lesson_id=L.lid and M.student_id= '2' );