在SQL语法基础一文中介绍了SQL的基本语法,接下来进行DQL的深层次学习。涉及到的表有学生表(student)、课程表(course)、选课表(sc)。
建表语句如下:
student表:
CREATE TABLE student(
Sno VARCHAR(7) PRIMARY KEY, -- 学号,主键
Sname VARCHAR(20) NOT NULL, -- 姓名
Ssex VARCHAR(2), -- 性别
Sage INT, -- 年龄
Sdept VARCHAR(20) -- 所在系
);
course表:
CREATE TABLE course(
Cno VARCHAR(10) PRIMARY KEY, -- 课程号,主键
Cname VARCHAR(20), -- 课程名
Credit INT -- 课程学分
);
CREATE TABLE sc(
Sno VARCHAR(7) NOT NULL, -- 学号
Cno VARCHAR(10) NOT NULL, -- 课程名
Grade INT, -- 成绩
PRIMARY KEY(Sno, Cno), -- 主键
FOREIGN KEY(Sno) REFERENCES student(Sno),-- 引用两个外键
FOREIGN KEY(Cno) REFERENCES course(Cno)
);
1.查询信息系所有学生的名字
select Sname from student where Sdept='信息系';
select * from student where Sdept = '信息系' and Sage < 20;
查询结果如下:
3.查询既不是信息系又不是数学系的学生学生信息
select * from student where Sdept not in('计算机系','数学系');
select * from student where Sname like '张%';
select * from student where Sname like '[张王李]%';
等价于:
select * from student where Sname like '张%' or Sname like '王%' or Sname like '李%';
select * from student where Sname like '王_'
select count(*) as 学生人数 from student;
查询结果如下:
8.统计每个系的学生人数和平均年年龄,并按平均年龄升序排列
select Sdept 系, count(*) 学生人数, AVG(Sage) 平均年龄 from Student GROUP BY Sdept ORDER BY 平均年龄 asc;
select sdept 系,count(*) 女生人数 from Student where Ssex='女' GROUP BY Sdept;
查询结果如下:
10.统计每个系的男生人数和女生人数,以及男生的最大年龄和女生的最大年龄.并按系名升序排列
select Sdept as 系,Ssex as 性别, count(*) as 人数,max(Sage) as 最大年龄 from student
group by Sdept,Ssex
order by Sdept;
查询结果如下:
11.查询没有考试成绩的学生的学号和相应的课程号
select Sno, Cno from sc where Grade is null;
select COUNT(DISTINCT Sno) from SC;
查询结果如下:
13.统计学号为2012101的学生选课门数及总成绩
select count(*) as 选课门数, sum(Grade) as 总成绩 from sc where Sno='2012101';
查询结果如下:
14.统计每门课程的选课人数,列出课程号和选课人数
select Cno 课程号, count(*) 总人数 from SC GROUP BY Cno;
select sno 学号, count(*) 选课门数, AVG(grade) 平均成绩 from sc group by sno;
查询结果如下:
16.统计选修了2门以上课程的学生学号和选课门数
select Sno 学号,count(*) 选课门数 from sc GROUP BY Sno having count(*)>2;
查询结果如下:
17.统计’c001’课程的平均成绩、最高分、最低分
select avg(Grade) as 平均成绩,max(Grade) as 最高分,min(Grade) 最低分 from sc where Cno='c001';
查询结果如下:
18.查询学号为2012106的同学选课门数、已考试课程门数、最高分、最低分、平均分
select count(*) as 选课门数,count(Grade) as 考试门数,max(Grade) as 最高分,min(Grade) as 最低分,avg(Grade) 平均成绩
from sc where Sno='2012106';
注:count(列名) 会去掉空值
查询结果如下:
19.查询平均成绩超过80 的学生的学号、选课门书数和平均成绩
select Sno as 学号,count(*) as 选课门数,avg(Grade) as 平均成绩 from sc group by Sno having 平均成绩>80
查询结果如下:
20. 统计每个系的男生人数,只列出男生人数大于2的系的名字和人数
select Sdept as 系, count(*) as 男生人数 from student group by Sdept having count(*)>2;
查询结果如下:
接下来进入多表连接查询:
21.查询每个学生及其选课信息
select student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade from student join sc on student.Sno=sc.Sno;
查询结果如下:
22.查询计算机系学生的选课情况,列出学生的学号、姓名、课程号和成绩
select sc.Sno,Sname,Cno,Grade from student join sc on student.Sno=sc.Sno where Sdept='计算机系';
查询结果如下:
23.统计’数学系’选修了’计算机文化学’课程的学生的成绩,列出学生的姓名、课程名和成绩
select Sname,Cname,Grade from student as s join sc on s.Sno=sc.Sno
join course c on c.Cno=sc.Cno
where Sdept='数学系' and Cname='计算机文化学';
查询结果如下:
24.统计’计算机文化学’课程考试成绩前三名的学生的姓名、所在系和成绩,并按成绩降序排列
select Sname,Sdept,Grade from student s join sc on s.Sno=sc.Sno
join course c on c.Cno=sc.Cno
where Cname='计算机文化学'
order by Grade desc limit 0,3 ;
select Sdept,avg(grade) as 平均成绩 from student s join sc on s.Sno=sc.Sno
group by Sdept;
查询结果如下:
26.统计’信息系’每门课程的的选课人数、平均成绩、最高成绩、最低成绩
select Cno ,count(*) as 选课人数,avg(Grade) as 平均成绩,max(Grade) as 最高分,min(Grade) as 最低分
from student as s join sc on s.Sno=sc.Sno
where Sdept='信息系'
group by Cno;
查询结果如下:
27.查询与吴冰在同一个系学习的同学,列出姓名和系名(这是一个自连接查询)
select s2.Sname,s2.Sdept from student s1 join student s2 on s1.Sdept=s2.Sdept
where s1.Sname='吴冰' and s2.Sname!='吴冰';
查询结果如下:
28.查询学生的选课情况,包括选了课程的同学和没有选课的同学(左外连接)
select student.Sno,Sname,Cno,Grade from student left join sc on student.Sno=sc.Sno;
查询结果如下:(可见比内连接结果多了一列)
29.查询那些同学没有选课
解析:没有选课的同学那么其信息一定在student表中有,而在sc表中没有,这里采用左外连接实现,把student表当做主表,不满足连接条件的列也将被查询出来,同时,sc表的相应字段为null,所以这里的筛选条件为sc表的任一字段都行,即sc.Cno is null 或者 sc.Grade is null都可。
select Sname from student s left join sc on s.Sno=sc.Sno where sc.Sno is null;
30.查询那些课程没有人选,列出课程号和课程名(分析思路和上一题一样)
select c.Cno,Cname from course c left join sc on c.Cno=sc.Cno where sc.Cno is null;
查询结果如下:
子查询
31.查询和吴冰在同一个系学习的学生(在27题中用自连接实现过)
select Sno,Sname,Sdept from student where Sdept in (
select Sdept from student where Sname='吴冰'
) and Sname!='吴冰';
查询结果如下:
32.查询考试成绩大于90分的学生的学号和姓名
select Sno,Sname from student where Sno in (select Sno from sc where grade>90);
也可用连接查询实现:
select s.Sno,Sname from student s join sc on s.Sno=sc.Sno where Grade>90;
查询结果如下:
33.查询选修了‘Java’课程的学生的学号和姓名
select Sno,Sname from student where Sno in
(select Sno from sc where Cno in
(select Cno from course where Cname='Java'));
也可用连接查询实现:
select s.Sno,Sname from student s join sc on s.Sno=sc.Sno
join course c on c.Cno=sc.Cno
where c.Cname='Java';
查询结果如下:
34.统计选修了‘计算机文化学’课程的学生的选课门数和平均成绩(这题就不能使用多表连接查询实现了)
select Sno, count(*) as 选课门数,avg(Grade) as 平均成绩 from sc where Sno in(
select Sno from sc join course c on sc.Cno=c.Cno where Cname='计算机文化学')
group by Sno;
select Sname,Sage from student where Sdept='信息系' and Sage =(
select max(Sage) from student where Sdept='信息系');
查询结果如下:
36.查询计算机文化学考试成绩高于计算机文化学平均成绩的学生的学号、姓名、所在系和课程成绩.
select s.Sno as 学号,Sname as 姓名,Sdept as 系,Grade as 成绩
from student as s join sc on s.Sno=sc.Sno
join course as c on sc.Cno=c.Cno
where Cname='计算机文化学' and Grade>
(select avg(Grade) from sc join course c on sc.Cno=c.Cno where Cname='计算机文化学');
查询结果如下:
37.查询计算机系没有选修计算机文化学的学生学号和姓名
select Sno,Sname from student where Sno not in (
select Sno from sc join course c on sc.Cno=c.Cno where Cname='计算机文化学' )
and Sdept='计算机系';
DQL查询指令多且复杂,平时需要多看多练,积跬步以至千里!