join
1、作用:
每个实体,一个表,一个业务逻辑,使用多个实体的数据,多张表应该在一起使用,将多个表的记录连接起来。
2、总体思路:
先将所有的数据,按照某种条件连接起来,再进行筛选处理。
3、概念:
1)内连接:
只有在连接的表内数据都存在的情况下,才会做连接。inner join
2)交叉连接(笛卡儿积):
内连接是可以省略连接条件的,意味着所有的左表的数据,都要和右表的记录做一个连接。共存在M*N个连接,这种连接就称之为交叉连接,或者笛卡儿积连接。两个二维表的没有条件的内连接就是笛卡尔积。也叫做交叉连结(cross join)
笛卡尔积(cartesian product),又叫直积,所有可能的组合。假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。
注意:
mysql中cross join与inner join相同,但在数据库的定义上,交叉连接就是笛卡儿积,是没有条件的inner join。mysql中inner join是默认的连接方式,可以省略inner。
3)有条件的内链接:
会在连接时过滤非法的连接;
where的写法:数据过滤,数据安装交叉连接完成后,再做数据过滤,
on的写法:在连接时,就对数据进行判断。
using的写法:using要求,负责连接的两个实体之间的字段名称一致。
4)外连接:
如果存在不能匹配的数据,也会进行连接,不过此时mysql会帮我们虚拟一条不存在的记录(字段值都是null),帮助我们完善整条连接记录。Mysql暂时不支持全外连接。
自然连接:mysql自己判断连接条件,自动连接。支持内自然连接和外自然连接。但mysql的实现相对简单,自然连接与不带条件的innerjoin相同。带sing条件的left join与 natrual left join相同。
4、语法:
inner join,cross join [条件]。没有条件就是笛卡尔积。
left join, right join 条件。左和右的区别在于,如果是左连接,那么即使左表的记录,连接不到,也会在最终结果内显示。
natrual [left|right] join,内可以省略条件,外必须使用条件。自然连接会重新规划列名,因此条件就不能是表名.字段名的形式。可以理解i成自然连接后,就成了一个表了。而 外和内是有连接条件的两个表。
5、条件:
Where和on可以使用条件表达式;using (公共字段),需要使用公共字段。
内联可以使用where on 和using条件;外联只可以使用using和on作为条件,外连接不能使用where。
通常 where还有筛选的含义,而on和using只有连接条件的意思。因此通常连接条件使用on或using。而筛选条件使用where加以区分。建议是,在有同名字段的时候使用using,而在通用条件时,使用on。在数据过滤时(不是指连接过滤)使用where。
6、测试用例1:
drop table if exists one;
create table one (
one_id int,
one_data char(1),
public_field int
);
insert into one values
(1, 'a', 10),
(2, 'b', 20),
(3, 'c', 30);
drop table if exists two;
create table two (
two_id int,
two_data char(1) not null default 't',
public_field int
);
insert into two values
(2, 'B', 20),
(3, 'C', 30),
(4, 'D', 40);
7、测试程序2:
join
#教师信息
create table join_teacher(
id int primary key auto_increment,
t_name varchar(10),
gender enum('male', 'female', 'secret')
)engine innodb character set utf8;
insert into join_teacher values
(1, '韩信','male'),
(2, '貂蝉', 'female'),
(3, '刘备', 'secret'),
(4, '孙权', 'male');
#班级信息
create table join_class(
id int primary key auto_increment,
c_name char(7),
room char(3)
)engine innodb character set utf8;
insert into join_class values
(1, 'php0115', '120'),
(2, 'php0224', '214'),
(3, 'php0232', '112'),
(4, 'php1111', '111');
#代课时间表
create table join_teacher_class(
id int primary key auto_increment,
t_id int,
c_id int,
days tinyint,
begin_date date,
end_date date
)engine innodb character set utf8;
insert into join_teacher_class values
(1, 1, 1, 15, '2013-01-12', '2016-01-12'),
(2, 1, 2, 16, '2012-01-12', '2013-01-12'),
(3, 1, 3, 19, '2013-05-12', '2016-01-12'),
(4, 2, 3, 20, '2013-03-01', '2015-01-12'),
(5, 3, 1, 19, '2014-05-12', '2015-01-12'),
(6, 1, 3, 21, '2012-02-11', '2017-01-12'),
(7, 3, 2, 16, '2012-05-07', '2013-01-12'),
(8, 1, 1, 19, '2015-01-12', '2016-01-12');
tbl1_left inner join tbl1_right on connect_condition
有条件内连接
select join_teacher.t_name, join_teacher_class.begin_date, join_teacher_class.days
from join_teacher inner join
join_teacher_class on join_teacher.id = join_teacher_class.t_id;
外连接
select join_teacher.t_name, join_teacher_class.begin_date, join_teacher_class.days
from join_teacher left outer join
join_teacher_class on
join_teacher.id = join_teacher_class.t_id;
默认内连接并且无条件
select join_teacher.t_name, join_teacher_class.begin_date, join_teacher_class.days
from join_teacher join
join_teacher_class;
where语句
select join_teacher.t_name, join_teacher_class.begin_date, join_teacher_class.days
from join_teacher inner join
join_teacher_class where
join_teacher.id = join_teacher_class.t_id;
select join_teacher.t_name, join_teacher_class.begin_date, join_teacher_class.days
from join_teacher inner join
join_teacher_class on
join_teacher.id = join_teacher_class.t_id and
days > 20;
select join_teacher.t_name, join_teacher_class.begin_date, join_teacher_class.days
from join_teacher inner join
join_teacher_class where
join_teacher.id = join_teacher_class.t_id where
days > 20;
最好的一种
select join_teacher.t_name, join_teacher_class.begin_date, join_teacher_class.days
from join_teacher inner join
join_teacher_class on
join_teacher.id = join_teacher_class.t_id where
days > 20;
别名的使用
select join_teacher.t_name, join_teacher.id as
t_id, join_teacher_class.id as
tc_id,join_teacher_class.begin_date, join_teacher_class.days from join_teacher inner join
join_teacher_class on
join_teacher.id = join_teacher_class.t_id ;
1.png
8、外连接
join左边的表就是左表,右边的表就是右表。
分类:
左边连接/右边连接/全外连接
左连接:left [outer] join
在左连接时,如果出现左边表,数据连接不到右边表的情况,则坐标表的数据在最终结果内被保留,而如果出现右边表的数据连接不到左边表的情况时,右表的数据就会被丢弃。
select join_teacher.t_name, join_teacher.id as
t_id, join_teacher_class.id as tc_id,
join_teacher_class.begin_date,
join_teacher_class.days from
join_teacher left join join_teacher_class on
join_teacher.id = join_teacher_class.t_id ;
1.png
9、自然连接
通过mysql自己的判断完成连接过程;不需要指定连接条件,mysql会使用多表内的,相同的字段,作为连接条件。
natural
select * from one natural join two;
select * from one inner join two using (public_field);
select * from one natural left join two;
select * from one left join two using (public_field);
select * from one natural right join two;
select * from one right join two using (public_field);
10、多表连接
多表连接
create table info_class(
id int,
class_name varchar(20)
);
create table info_student(
id int,
student_name varchar(20),
class_id int
);
create table info_student_info(
id int,
student_detail varchar(50)
);
select * from info_class as c left join
info_student as s on
c.id = s.class_id left join
info_student_info as si on
s.id = si.id where c.class_name = 'php0331';
1.png
网友评论