连接查询
当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回
等值连接查询:查询的结果为两个表匹配到的数据
左连接查询:查询的结果为两个表匹配到的数据加左表特有的数据,对于右表中不存在的数据使用null填充
右连接查询:查询的结果为两个表匹配到的数据加右表特有的数据,对于左表中不存在的数据使用null填充
准备数据
drop table if exists courses;
create table courses (
courseNo int(10) unsigned primary key auto_increment,
name varchar(10));
insert into courses values
(‘1’, ‘数据库’),
(‘2’, ‘qtp’),
(‘3’, ‘linux’),
(‘4’, ‘系统测试’),
(‘5’, ‘单元测试’),
(‘6’, ‘测试过程’);
drop table if exists scores;
create table scores (
id int(10) unsigned primary key auto_increment,
courseNo int(10), studentno varchar(10),
score tinyint(4));
insert into scores values
(‘1’, ‘1’, ‘001’, ‘90’),
(‘2’, ‘1’, ‘002’, ‘75’),
(‘3’, ‘2’, ‘002’, ‘98’),
(‘4’, ‘3’, ‘001’, ‘86’),
(‘5’, ‘3’, ‘003’, ‘80’),
(‘6’, ‘4’, ‘004’, ‘79’),
(‘7’, ‘5’, ‘005’, ‘96’),
(‘8’, ‘6’, ‘006’, ‘80’);
等值连接
方式一
select * from 表1,表2 where 表1.列=表2.列
方式二(又称内连接)
select * from 表1 inner join 表2 on 表1.列=表2.列
例1:查询学生信息及学生的成绩
select *from students stu, scores scwhere stu.studentNo = sc.studentNo
select *from students stu inner join scores sc on stu.studentNo = sc.studentNo
例2:查询课程信息及课程的成绩
select *from courses cs, scores scwhere cs.courseNo = sc.courseNo
select *from courses csinner join scores sc on cs.courseNo = sc.courseNo
例3:查询学生信息及学生的课程对应的成绩
select *from students stu, courses cs, scores scwhere stu.studentNo = sc.studentno and cs.courseNo = sc.courseNo
select *from students stuinner join scores sc on stu.studentNo = sc.studentNoinner join courses cs on cs.courseNo = sc.courseNo
例4:查询王昭君的成绩,要求显示姓名、课程号、成绩
select stu.name, sc.courseNo, sc.score from students stu, scores scwhere stu.studentNo = sc.studentNo and stu.name = ‘王昭君’
select stu.name, sc.courseNo, sc.scorefrom students stuinner join scores sc on stu.studentNo = sc.studentNowhere stu.name = ‘王昭君’
例5:查询王昭君的数据库成绩,要求显示姓名、课程名、成绩
select stu.name, cs.name, sc.scorefrom students stu, scores sc, courses cswhere stu.studentNo = sc.studentNo and sc.courseNo = cs.courseNo and stu.name = ‘王昭君’ and cs.name = ‘数据库’
select stu.name, cs.name, sc.scorefrom students stuinner join scores sc on stu.studentNo = sc.studentNoinner join courses cs on sc.courseNo = cs.courseNowhere stu.name = ‘王昭君’ and cs.name = ‘数据库’
例6:查询所有学生的数据库成绩,要求显示姓名、课程名、成绩
select stu.name, cs.name, sc.score from students stu, scores sc, courses cswhere stu.studentNo = sc.studentNo and sc.courseNo = cs.courseNo and cs.name = ‘数据库’
select stu.name, cs.name, sc.scorefrom students stuinner join scores sc on stu.studentNo = sc.studentNoinner join courses cs on sc.courseNo = cs.courseNowhere cs.name = ‘数据库’
例7:查询男生中最高成绩,要求显示姓名、课程名、成绩
select stu.name, cs.name, sc.scorefrom students stu, scores sc, courses cswhere stu.studentNo = sc.studentNo and sc.courseNo = cs.courseNo and stu.sex = '男’order by sc.score desclimit 1
select stu.name, cs.name, sc.scorefrom students stuinner join scores sc on stu.studentNo = sc.studentNoinner join courses cs on sc.courseNo = cs.courseNowhere stu.sex = '男’order by sc.score desclimit 1
左连接
select * from 表1left join 表2 on 表1.列=表2.列
例1:查询所有学生的成绩,包括没有成绩的学生
select *from students stuleft join scores sc on stu.studentNo = sc.studentNo
例2:查询所有学生的成绩,包括没有成绩的学生,需要显示课程名
select *from students stuleft join scores sc on stu.studentNo = sc.studentNoleft join courses cs on cs.courseNo = sc.courseNo
右连接
select * from 表1right join 表2 on 表1.列=表2.列
添加两门课程
insert into courses values (0, ‘语文’),(0, ‘数学’);
例1:查询所有课程的成绩,包括没有成绩的课程
select *from scores scright join courses cs on cs.courseNo = sc.courseNo
例2:查询所有课程的成绩,包括没有成绩的课程,包括学生信息
select *from scores scright join courses cs on cs.courseNo = sc.courseNoleft join students stu on stu.studentNo = sc.studentNo
自关联
设计省信息的表结构provinces
id
ptitle
设计市信息的表结构citys
id
ctitle
proid
citys表的proid表示城市所属的省,对应着provinces表的id值
问题:能不能将两个表合成一张表呢?
思考:观察两张表发现,citys表比provinces表多一个列proid,其它列的类型都是一样的
意义:存储的都是地区信息,而且每种信息的数据量有限,没必要增加一个新表,或者将来还要存储区、乡镇信息,都增加新表的开销太大
答案:定义表areas,结构如下
id
atitle
pid
因为省没有所属的省份,所以可以填写为null
城市所属的省份pid,填写省所对应的编号id
这就是自关联,表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一样的,城市信息的pid引用的是省信息的id
在这个表中,结构不变,可以添加区县、乡镇街道、村社区等信息
准备数据:
create table areas(
aid int primary key,
atitle varchar(20),
pid int);
insert into areas values
(‘130000’, ‘河北省’, NULL),
(‘130100’, ‘石家庄市’, ‘130000’),
(‘130400’, ‘邯郸市’, ‘130000’),
(‘130600’, ‘保定市’, ‘130000’),
(‘130700’, ‘张家口市’, ‘130000’),
(‘130800’, ‘承德市’, ‘130000’),
(‘410000’, ‘河南省’, NULL),
(‘410100’, ‘郑州市’, ‘410000’),
(‘410300’, ‘洛阳市’, ‘410000’),
(‘410500’, ‘安阳市’, ‘410000’),
(‘410700’, ‘新乡市’, ‘410000’),
(‘410800’, ‘焦作市’, ‘410000’);
例1:查询一共有多少个省
select count(*) from areas where pid is null;
例1:查询河南省的所有城市
select * from areas as pinner join areas as c on c.pid=p.aidwhere p.atitle=‘河北省’;
添加区县数据
insert into areas values
(‘410101’, ‘中原区’, ‘410100’),
(‘410102’, ‘二七区’, ‘410100’),
(‘410103’, ‘金水区’, ‘410100’);
例2:查询郑州市的所有区县
select * from areas as cinner join areas as a on a.pid=c.aidwhere c.atitle=‘郑州市’;
例3:查询河南省的所有区县
select * from areas as pleft join areas as c on c.pid=p.aidleft join areas as a on a.pid=c.aidwhere p.atitle=‘河南省’
子查询
在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句
主查询
主要查询的对象,第一条 select 语句
主查询和子查询的关系
子查询是嵌入到主查询中
子查询是辅助主查询的,要么充当条件,要么充当数据源
子查询是可以独立存在的语句,是一条完整的 select 语句
子查询分类
标量子查询: 子查询返回的结果是一个数据(一行一列)
列子查询: 返回的结果是一列(一列多行)
行子查询: 返回的结果是一行(一行多列)
表级子查询: 返回的结果是多行多列标量子查询
例1:查询班级学生的平均年龄查询班级学生平均年龄
select avg(age) from students
查询大于平均年龄的学生
select * from students where age > 21.4167
select * from students where age > (select avg(age) from students);
例2:查询王昭君的成绩,要求显示成绩学生表中查询王昭君的学号
select studentNo from students where name = ‘王昭君’
成绩表中根据学号查询成绩
select * from scores where studentNo = '001’select * from scores where studentNo = (select studentNo from students where name = ‘王昭君’)
列级子查询
例3:查询18岁的学生的成绩,要求显示成绩学生表中查询18岁的学生的学号
select studentNo from students where age=18
成绩表中根据学号查询成绩s
elect * from scores where studentNo in (‘002’,‘006’)select * from scores where studentNo in (select studentNo from students where age=18)
行级子查询例4:查询男生中年龄最大的学生信息
select * from students where sex=‘男’ and age=(select max(age) from students)
select * from students where (sex,age)=(‘男’,30)
select * from students where (sex,age) = (select sex,age from students where sex=‘男’ order by age desc limit 1)
表级子查询
例5:查询数据库和系统测试的课程成绩
select * from scores sinner join (select * from courses where name in (‘数据库’,‘系统测试’)) con s.courseNo = c.courseNo
子查询中特定关键字使用
in 范围
格式: 主查询 where 条件 in (列子查询)
any | some 任意一个
格式: 主查询 where 列 = any (列子查询)
在条件查询的结果中匹配任意一个即可,等价于 in
all
格式: 主查询 where 列 = all(列子查询) : 等于里面所有
格式: 主查询 where 列 <>all(列子查询) : 不等一其中所有
select * from students where age in (select age from students where age between 18 and 20)