图解MySQL 内链接、外链接、左链接、右链接、全链接……太多了

图解MySQL 内链接、外链接、左链接、右链接、全链接……太多了

 

用两个表(a_table、b_table),关联字段a_table.a_id和b_table.b_id来演示一下MySQL的内链接、外链接( 左(外)链接、右(外)链接、全(外)链接)。php

MySQL版本:Server version: 5.6.31 MySQL Community Server (GPL)html

数据库表:a_table、b_tablemysql

主题:内链接、左链接(左外链接)、右链接(右外链接)、全链接(全外链接)sql

前提

建表语句:

CREATE TABLE `a_table` ( `a_id` int(11) DEFAULT NULL, `a_name` varchar(10) DEFAULT NULL, `a_part` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8

 

CREATE TABLE `b_table` ( `b_id` int(11) DEFAULT NULL, `b_name` varchar(10) DEFAULT NULL, `b_part` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8

表测试数据:


1、内链接

关键字:inner join on
语句:select * from a_table a inner join b_table bon a.a_id = b.b_id;
执行结果:

说明:组合两个表中的记录,返回关联字段相符的记录,也就是返回两个表的交集(阴影)部分。

2、左链接(左外链接)

关键字:left join on / left outer join on
语句:select * from a_table a left join b_table bon a.a_id = b.b_id;
执行结果:
 
说明:
left join 是left outer join的简写,它的全称是左外链接,是外链接中的一种。
左(外)链接,左表(a_table)的记录将会所有表示出来,而右表(b_table)只会显示符合搜索条件的记录。右表记录不足的地方均为NULL。

3、右链接(右外链接)

关键字:right join on / right outer join on
语句:select * from a_table a right outer join b_table b on a.a_id = b.b_id;
执行结果:

说明:
right join是right outer join的简写,它的全称是右外链接,是外链接中的一种。
与左(外)链接相反,右(外)链接,左表(a_table)只会显示符合搜索条件的记录,而右表(b_table)的记录将会所有表示出来。左表记录不足的地方均为NULL。


4、全链接(全外链接)

MySQL目前不支持此种方式,能够用其余方式替代解决。

5、补充,MySQL如何执行关联查询

MySQL认为任何一个查询都是一次“关联”,并不只仅是一个查询须要到两个表匹配才叫关联,因此在MySQL中,每个查询,每个片断(包括子查询,甚至基于单表查询)均可以是一次关联。
当前MySQL关联执行的策略很简单:MySQL对任何关联都执行嵌套循环关联操做,即MySQL先在一个表中循环取出单条数据,而后在嵌套循环到下一个表中寻找匹配的行,依次下去,直到找到全部表中匹配的行为止。而后根据各个表匹配的行,返回查询中须要的各个列。请看下面的例子中的简单的查询:
 
查询语句:select tbl1.col1, tbl2.col2 from tbl1 inner join tbl2 using(col3) where tbl1.col1 in (5, 6);
假设MySQL按照查询中的表顺序进行关联操做,咱们则能够用下面的伪代码表示MySQL将如何完成这个查询:
outer_iter = iterator over tbl1 where col1 in (5, 6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end outer_row = outer_iter.next end

 

上面的执行计划对于单表查询和多表关联查询都适用,若是是一个单表查询,那么只须要上面外层的基本操做。对于外链接,上面的执行过程仍然适用。例如,咱们将上面的查询语句修改以下:
select tbl1.col1, tbl2.col2 from tbl1 left outer join tbl2 using(col3) where tbl1.col1 in (5, 6);
那么,对应的伪代码以下:
outer_iter = iterator over tbl1 where col1 in (5, 6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next if inner_row while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end else output [ outer_row.col1, null] end outer_row = outer_iter.next end

 

说明:第五部分摘自《高性能MySQL 第三版》
 

数据库之联合查询和链接查询

1.JOIN和UNION区别
join 是两张表作交连后里面条件相同的部分记录产生一个记录集,
union是产生的两个记录集(字段要同样的)并在一块儿,成为一个新的记录集。

JOIN用于按照ON条件联接两个表,主要有四种:
INNER JOIN:内部联接两个表中的记录,仅当至少有一个同属于两表的行符合联接条件时,内联接才返回行。我理解的是只要记录不符合ON条件,就不会显示在结果集内。
LEFT JOIN / LEFT OUTER JOIN:外部联接两个表中的记录,并包含左表中的所有记录。若是左表的某记录在右表中没有匹配记录,则在相关联的结果集中右表的全部选择列表列均为空值。理解为即便不符合ON条件,左表中的记录也所有显示出来,且结果集中该类记录的右表字段为空值。
RIGHT JOIN / RIGHT OUTER JOIN:外部联接两个表中的记录,并包含右表中的所有记录。简单说就是和LEFTJOIN反过来。
FULL JOIN / FULL OUTER JOIN:完整外部联接返回左表和右表中的全部行。就是LEFTJOIN和RIGHTJOIN和合并,左右两表的数据都所有显示。数据库

JOIN的基本语法:
Select table1.* FROM table1 JOIN table2 ON table1.id=table2.idmarkdown

sql写法
内链接innerjoin:
SELECT msp.name, party.name
FROM msp JOIN party ON party=code

SELECT msp.name, party.name
FROM msp inner JOIN party ON party=code

左链接leftjoin :
SELECT msp.name, party.name
FROM msp LEFT JOIN party ON party=code

右链接rightjoin :
SELECT msp.name, party.name
FROM msp RIGHT JOIN party ON msp.party=party.codepost

全链接(fulljoin):
SELECT msp.name, party.name
FROM msp FULL JOIN party ON msp.party=party.code性能

 

UNION运算符
将两个或更多查询的结果集组合为单个结果集,该结果集包含联合查询中的全部查询的所有行。UNION的结果集列名与UNION运算符中第一个Select语句的结果集的列名相同。另外一个Select语句的结果集列名将被忽略。
其中两种不一样的用法是UNION和UNIONALL,区别在于UNION从结果集中删除重复的行。若是使用UNIONALL 将包含全部行而且将不删除重复的行。测试

UNION和UNIONALL的区别:
union 检查重复
union all 不作检查
好比select 'a' union select 'a' 输出就是一行 a
好比select 'a' union all select 'a' 输出就是两行 aatom

2.经过下面的例子,能够清晰的看出和理解2者的区别
实例1典型的二表链接演示

假定有两个表Table1和Table2,其包含的列和数据分别如表1.1和表1.2所示。

表1.1Table1数据库

 

ColumnA

ColumnB

ColumnC

X1

Y1

Z1

X2

Y2

Z2

X3

Y3

Z3

 

表1.2Table2数据库表

 

ColumnA

ColumnD

ColumnE

X1

D1

E1

X2

D2

E2

X3

D3

E3

 

Table1和Table2表共有的列为ColumnA,若是经过ColumnA列的值链接Table1和Table2两个表,即链接条件为Table1.ColumnA=Table2.ColumnA,此时获得的链接结果如表1.3所示。

表1.3 链接Table1和Table2表

ColumnA

ColumnB

ColumnC

ColumnD

ColumnE

X1

Y1

Z1

D1

E1

X2

Y2

Z2

D2

E2

X3

Y3

Z3

D3

E3

上述链接过程的实现代码可表示以下:SELECT* FROM Table1 JOIN Table2 ON Table1.ColumnA=Table2.columnA

实例2 典型的二表记录的UNION运算

假定有两个表Table3和Table4,其包含的列和数据分别如表2.1和表2.2所示。

表2.1Table3数据库表

 

ColumnA

ColumnB

ColumnC

X1

Y1

Z1

X2

Y2

Z2

X3

Y3

Z3

 

表2.2Table4数据库表、

 

ColumnA

ColumnD

ColumnE

X4

Y4

Z4

X5

Y5

Z5

X6

Y6

Z6

 

Table3表和Table4表具备相同的列结构,列数也要相同,列名能够不一样,以第一个表的列名为新表的列名,所以可使用UNION运算符链接两个表的记录集,获得的链接结果如表2.3所示。

表2.3 使用UNION链接Table3表和Table4表的记录

 

ColumnA

ColumnB

ColumnC

X1

Y1

Z1

X2

Y2

Z2

X3

Y3

Z3

X4

Y4

Z4

X5

Y5

Z5

X6

Y6

Z6

上述链接过程的实现代码可表示以下:SELECT * FROM Table3 UNION SELECT *FROMTable4

 

SQL语法——left join on 多条件

 

left join on +多条件与where区别

重点

先匹配,再筛选where条件。


本文将经过几个例子说明二者的差异。

表1:product

id amount
1 100
2 200
3 300
4 400

表2:product_details

id weight exist
2 22 0
4 44 1
5 55 0
6 66 1

1. 单个条件

select * from product a
left join  product_details b
on a.id  = b.id

以左表为准匹配,结果:

id amount id weight exist
1 100 null null null
2 200 2 22 0
3 300 null null null
4 400 4 44 1

2. 条件写在on 与where区别

查询1:

SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
AND   product.amount=200;

结果:

id amount id weight exist
1 100 null null null
2 200 2 22 0
3 300 null null null
4 400 null null null

把on的全部条件做为匹配条件,不符合的右表都为null。
查询2:

SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
WHERE product.amount=200;

 

id amount id weight exist
2 200 2 22 0

匹配完再筛选,结果只有一条记录。

3. where XXX is null 状况

使用该语句表示:删除掉不匹配on后面条件的记录。
where XXX is not null 则表示筛选出符合on后面条件的记录。
经常使用于只须要左表的数据,好比count id这类。

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id AND b.weight!=44 AND b.exist=0
WHERE b.id IS NULL;

结果:

id amount
1 100
3 300
4 400

能够直观看出,只有id=2的纪录彻底匹配上三个条件,因此筛除这条纪录,另三条保留,此时这三条纪录的右表均为null。
筛选出不符合on后面条件的,即 !(a.id=b.id AND b.weight!=44 AND b.exist=0).
!(a.id=b.id AND || !(b.weight!=44) || !(b.exist=0).
(a.id != b.id AND || (b.weight = 44) || ( b.exist! = 0).
逻辑 AND 和 逻辑 OR表达式,其操做数是从左到右求值的。若是第一个参数作够判断操做结果,那么第二个参数便不会被计算求值(短路效果)。

下面语句与该语句效果相同:(这里相同指的是最后只用到左表数据,如果将右表数据写出来是不同的)

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id
WHERE b.id is null OR b.weight=44 OR b.exist=1;

 

将on的否认条件写在where后,效果相同。

注:
若是你使用 LEFT JOIN 来寻找在一些表中不存在的记录,你须要作下面的测试:WHERE 部分的 col_name IS NULL,MYSQL 在查询到一条匹配 LEFT JOIN 条件后将中止搜索更多行(在一个特定的组合键下)。

参考:https://blog.csdn.net/czhphp/article/details/18657341

相关文章
相关标签/搜索