join 用于多表中字段之间的联系
JOIN 按照功能大致分为如下三类:
INNER JOIN(内连接,或等值连接):取得两个表中存在连接匹配关系的记录。
LEFT JOIN(左连接):取得左表(table1)完全记录,即是右表(table2)并无对应匹配记录。
RIGHT JOIN(右连接):与 LEFT JOIN 相反,取得右表(table2)完全记录,即是左表(table1)并无匹配对应记录。
注意:mysql不支持Full join,不过可以通过UNION 关键字来合并 LEFT JOIN 与 RIGHT JOIN来模拟FULL
先创建2个表
create table testa(aid int,aname varchar(100));
create table testb(bid int,bname varchar(100),age int);
insert into testa values(1,‘America’);
insert into testa values(2,‘China’);
insert into testa values(3,‘Japan’);
insert into testa values(4,‘British’);
insert into testa values(5,‘India’);
insert into testb values(1,‘Australia’,15);
insert into testb values(2,‘Korea’,16);
insert into testb values(3,‘Japan’,17);
insert into testb values(4,‘India’,18);
insert into testb values(7,‘Europe’,19);
insert into testb values(8,‘Russia’,20);
insert into testb values(9,‘Germany’,21);
left join,(或left outer join:在Mysql中两者等价,推荐使用left join.)左连接从左表(A)产生一套完整的记录,与匹配的记录(右表(B)) .如果没有匹配,右侧将包含null。
select
a.aid,a.aname,
b.bid,b.bname
from
testa a left join testb b on a.aid=b.bid;
格式:
select
a表字段1,字段2
b表字段1,字段2
from
a表 xxx(别名) left join b表 yyy(别名)on a表字段1(2)=b表字段1(2)
别名可以不要,下同
如果想只从左表(A)中产生一套记录,但不包含右表(B)的记录,可以通过设置where语句来执行,如:
select
a.aid,a.aname,
b.bid,b.bname
from
testa a left join testb b on a.aid=b.bid
where a.aid is null or b.bid is null;
与左连接相似:
select
a.aid,a.aname,
b.bid,b.bname
from
testa a right join testb b on a.aid=b.bid;
格式:
select
a表字段1,字段2
b表字段1,字段2
from
a表 xxx(别名) right join b表 yyy(别名)on a表字段1(2)=b表字段1(2)
right同样也可以使用where语句筛选目标条件:
select
a.aid,a.aname,
b.bid,b.bname
from
testa a right join testb b on a.aid=b.bid
where a.aid is null or b.bid is null;
inner join产生同时符合A和B的一组数据。
select
a.aid,a.aname,
b.bid,b.bname
from
testa a inner join testb b on a.aid=b.bid;
格式:
select
a表字段1,字段2
b表字段1,字段2
from
a表 xxx(别名) inner join b表 yyy(别名)on a表字段1(2)=b表字段1(2)
根据id和name匹配
(1)左连接
select
a.aid,a.aname,
b.bid,b.bname
from
testa a left join testb b
on a.aid=b.bid and a.aname=b.bname;
格式:
select
a表字段1,字段2
b表字段1,字段2
from
a表 xxx(别名) left join b表 yyy(别名)
on a表字段1=b表字段1,a表字段2=b表字段2;
(2)右连接
select
a.aid,a.aname,
b.bid,b.bname
from
testa a right join testb b
on a.aid=b.bid and a.aname=b.bname;
格式:
select
a表字段1,字段2
b表字段1,字段2
from
a表 xxx(别名) right join b表 yyy(别名)
on a表字段1=b表字段1,a表字段2=b表字段2;
(3)内连接
select
a.aid,a.aname,
b.bid,b.bname
from
testa a inner join testb b
on a.aid=b.bid and a.aname=b.bname;
格式:
select
a表字段1,字段2
b表字段1,字段2
from
a表 xxx(别名) inner join b表 yyy(别名)
on a表字段1=b表字段1,a表字段2=b表字段2;
使用上次使用的三个表:部门表、工资等级表、员工表
(1)查询一个员工的部门坐落在哪个地方
select
a.ename,a.deptno,
b.dname,b.loc
from
emp a left join dept b on a.deptno=b.deptno;
格式:
select
员工表的员工名,员工表的部门编号,
部门表的部门编号,部门坐落位置
from
员工表 a left join 部门表 b on a.部门编号=b.部门编号;
(2)员工的所属部门是什么?在什么地方?所属的工资等级是什么?
原理同上,只是多添加了一个条件
select
a.ename,a.deptno,(a.sal+a.comm) as sal,
s.grade,
b.dname,b.loc
from
emp a left join dept b on a.deptno=b.deptno (先将员工匹配的部门位置筛选出来)
left join salgrade s on (a.sal+a.comm) between s.losal and s.hisal;(
再将薪水限制在最高和最低薪水之间匹配等级)
那么问题来了,使用以上语法执行脚本,发现薪水这一列数值出现null值,原本薪水+奖金肯定是一个数值,这里显示不出来是因为奖金如果是数值0的话,会显示null值,null与一个具体的数值相加减最后输出的还是null值,使得薪水这一列同样也出现null值,自然薪水等级显示不出来,所以需要对奖金为0的数值进行输出限定,赋予数值0输出,使用函数IFNULL(对应字段, 0)
select
a.ename,a.deptno,a.sal,IFNULL(a.comm, 0) comm,(a.sal+IFNULL(a.comm, 0)) as salcomm,
b.dname,b.loc
from emp a
left join dept b on a.deptno=b.deptno;
可以看到薪水和奖金都是有数值的了,那么再进行之前的语法操作,就能显示每个人的薪水等级:
select
a.ename,a.deptno,(a.sal+IFNULL(a.comm, 0)) as salcomm ,
s.grade,
b.dname,b.loc
from emp a
left join dept b on a.deptno=b.deptno
left join salgrade s
on (a.sal+IFNULL(a.comm, 0)) between s.losal and s.hisal;
null与数值相加减必为null,需将null输出为0;
left join在一个脚本种不止一个,可根据实际情况对相应的字段进行多个筛选
on后面可以关联><或者between…and…
学习链接
---------------------------------------------------未完待续-----------------------------------------------------