day08:多表查询

首先新建两张表(beanty表和boys表)

create table beauty(
id int(55),
bename varchar(55),
sex varchar(55),
boyfriendid int(55)
);

create table boys(
id int(55),
byname varchar(55)
);

分别向表中添加数据

insert into beauty(id,bename,sex) values(1,'柳岩','35');
insert into beauty(id,bename,sex,boyfriendid) values(2,'Angelababy','33',3);
insert into beauty(id,bename,sex,boyfriendid) values(3,'小昭','28',1);
insert into beauty(id,bename,sex,boyfriendid) values(4,'赵敏','26',1);
insert into beauty(id,bename,sex,boyfriendid) values(5,'小龙女','30',2);
insert into beauty(id,bename,sex,boyfriendid) values(6,'周芷若','29',1);
insert into beauty(id,bename,sex) values(7,'周冬雨','26');
insert into beauty(id,bename,sex) values(8,'迪丽热巴','26');


insert into boys(id,byname) values(1,'张无忌');
insert into boys(id,byname) values(2,'杨过');
insert into boys(id,byname) values(3,'黄晓明');
insert into boys(id,byname) values(4,'猪八戒');
insert into boys(id,byname) values(5,'孙悟空');

查询每个女神以及对应的男朋友的姓名

select bename,byname from beauty,boys;

查询结果不符合现实:

笛卡尔乘积现象:表1有m行,表2有n行,查询结果=m*n;

发生的原因:没有有效的连接条件

正确:添加有效的连接条件

select bename,byname from beauty,boys where beauty.boyfriendid=boys.id;

多表查询又称连接查询

含义:当查询的字段来自于多个表时,就需要用到多表查询

分类:内连接、外连接、交叉连接

新建:员工表和部门表

#员工表
create table employee(
id int(55),
ename varchar(55),
sex varchar(55),
leaderid int(55),
pay int(55),
departmentid int(55)
);

#部门表
create table department(
id int(55),
dname varchar(55)
);

#等级表
create table grade(
id int(55),
min int(55),
max int(55),
level varchar(55)
);

分别向表中添加数据:

insert into employee(id,ename,sex,leaderid,pay,departmentid) values(101,'张三','','104',6999,201901);
insert into employee(id,ename,sex,leaderid,pay,departmentid) values(102,'李四','','104',5999,201901);
insert into employee(id,ename,sex,leaderid,pay,departmentid) values(103,'王五','','102',4999,201902);
insert into employee(id,ename,sex,leaderid,pay,departmentid) values(104,'赵六','','101',4999,201903);
insert into employee(id,ename,sex,leaderid,pay,departmentid) values(105,'小强','','101',3999,201901);
insert into employee(id,ename,sex,leaderid,pay,departmentid) values(106,'老王','','102',3999,201902);
insert into employee(id,ename,sex,leaderid,pay,departmentid) values(107,'王二','','101',2999,201903);

insert into department(id,dname) values(201901,'技术部');
insert into department(id,dname) values(201902,'市场部');
insert into department(id,dname) values(201903,'后勤部');

insert into grade(id,min,max,level) values(1,2000,3000,'c');
insert into grade(id,min,max,level) values(2,3000,4000,'d');
insert into grade(id,min,max,level) values(3,4000,5000,'b');
insert into grade(id,min,max,level) values(4,5000,6000,'a');

内连接:等值连接、非等值连接、自连接 

等值连接:

查询员工姓名以及对应的部门名称

select  ename,dname from employee,department where employee.departmentid=department.id;

select  ename,dname from employee e,department d where e.departmentid=d.id;

select  e.ename,d.dname from employee e,department d where e.departmentid=d.id;

非等值连接:

查询员工的姓名以及对应的等级

select ename,level from employee e,grade g where e.pay<g.max and e.pay>g.min;

select ename,level from employee e,grade g where e.pay between g.min and g.max;

自连接:

查询员工的姓名以及对应的上级姓名

select e.ename 领导姓名,m.ename 员工姓名 from employee e,employee m where m.leaderid=e.id;

sql92的语法:

select  查询列表  from  表1  别名,表2  别名  where  连接条件  and  筛选条件;

sql99的语法:

select  查询列表   from  表1  别名  [连接类型]   join  表2  别名  on  连接条件  where  筛选条件;

连接类型:

内连接  :inner

外连接 :

  左外:left  【outer】

  右外:right 【outer】

  全外:full  【outer】

交叉连接:cross   

一、内连接:

语法:select   查询列表   from  表1  别名  inner  join  表2  别名  on  连接条件  where   筛选条件;

1)、等值连接:

查询员工姓名以及对应的部门名称

select   ename,dname  from  employee e  inner join  department  d  on  e.departmentid=d.id;

2)、非等值连接

查询员工的姓名以及对应的等级

select  ename,level  from  employee  e  inner  join  grade  on  e.pay>g.min  and  e.pay<g.max;

select  ename,level  from  employee  e  inner  join  grade  g on  e.pay  between  g.min  and  g.max;

3)、自连接

查询员工的姓名以及对应的上级姓名

select  e.ename,m.ename  from  employee e  inner join  employee m  on e.leaderid=m.id;

二、外连接

应用场景:用于查询一个表中有,另一个表中没有的记录

特点:外连接的查询结果为主表中的所有记录,如果从表中有和它匹配的,则显示匹配的值。如果从表中没有和它匹配的,则显示为null。

外连接的查询结果 = 内连接  +  主表中有而从表中没有的记录

左外连接中:left左边的是主表   ;  右外连接中:right  join  右边的是主表   ;  左外和右外交换两个表的顺序可以实现同样的效果

新建学生表student和成绩表score

create table student(
id varchar(55),
sname varchar(55),
age int(55),
class varchar(55),
sex varchar(55)
);

create table score(
id varchar(55),
cname varchar(55),
fraction int(55),
sid varchar(55)
);

分别向表中添加数据:

insert into student(id,sname,age,class,sex) values('101','张三',21,'软件技术班','');
insert into student(id,sname,age,class,sex) values('102','李四',23,'软件技术班','');
insert into student(id,sname,age,class,sex) values('103','王五',22,'软件技术班','');
insert into student(id,sname,age,class,sex) values('104','赵六',24,'软件技术班','');
insert into student(id,sname,age,class,sex) values('105','小强',18,'软件技术班','');
insert into student(id,sname,age,class,sex) values('106','老王',40,'软件技术班','');
insert into student(id,sname,age,class,sex) values('107','嗝屁老王',100,'软件技术班','');


insert into score(id,cname,fraction,sid) values('m123','MySQL',90,'101');
insert into score(id,cname,fraction,sid) values('m123','MySQL',89,'102');
insert into score(id,cname,fraction,sid) values('m123','MySQL',96,'106');

insert into score(id,cname,sid) values('m123','MySQL','103');
insert into score(id,cname,sid) values('m123','MySQL','104');
insert into score(id,cname,sid) values('m123','MySQL','105');


insert into score(id,cname,fraction,sid) values('j456','Java',78,'101');
insert into score(id,cname,fraction,sid) values('j456','Java',85,'103');
insert into score(id,cname,fraction,sid) values('j456','Java',95,'106');

insert into score(id,cname,sid) values('j456','Java','102');
insert into score(id,cname,sid) values('j456','Java','104');
insert into score(id,cname,sid) values('j456','Java','105');

insert into score(id,cname,fraction,sid) values('m123','ps',99,'100');

1)、左外连接

查询所有学生的姓名和各科成绩

select  sname,cname,fraction  from  student s left  join  score c  on s.id=c.sid;

查询所有学生的姓名和MySQL的成绩

select  sname,cname,fraction  from  student s left  join  score c  on s.id=c.sid where c.cname='mysql';

2)、右外连接

查询所有学生的姓名和各科成绩

select  sname,cname,fraction  from   score c  right  join  student s  on s.id=c.sid;

查询所有学生的姓名和Java的成绩

select  sname,cname,fraction  from   score c  right  join  student s  on s.id=c.sid where c.cname='Java';

3)、全外连接

全外连接 = 内连接 + 表1中有但表2中没有 + 表2中有但表1中没有的记录

select  sname,cname,fraction from score  c  full  join student  s  on  s.id=c.sid;   

由于mysql不支持full join,所以会报错,可以用left  join一次,加上union,再来right  join实现全连接的效果。

select sname,cname,fraction 
from student s left join score c on s.id=c.sid 
UNION
select sname,cname,fraction 
from student s right join score c on s.id=c.sid;

三、交叉连接

笛卡尔乘积

select  sname,cname,fraction from score  cross join  student;

sql92和sql99比较

1、功能方面:sql99支持的较多
2、可读性:sql99实现了连接条件和筛选条件的分离,因此可读性较高

原文地址:https://www.cnblogs.com/wuguiyu/p/11592399.html