您的位置:首页 > 数据库 > MySQL

mysql left join分析

2014-03-14 14:01 197 查看
mysql> desc product1;

+--------+------------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+--------+------------------+------+-----+---------+-------+

| id | int(10) unsigned | NO | PRI | 0 | |

| amount | int(10) unsigned | YES | | NULL | |

+--------+------------------+------+-----+---------+-------+

2 rows in set (0.01 sec)

mysql> desc product_details;

+--------+------------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+--------+------------------+------+-----+---------+-------+

| id | int(10) unsigned | NO | PRI | NULL | |

| weight | int(10) unsigned | YES | | NULL | |

| exist | int(10) unsigned | YES | | NULL | |

+--------+------------------+------+-----+---------+-------+

3 rows in set (0.00 sec)



mysql> select * from product1;

+----+--------+

| id | amount |

+----+--------+

| 1 | 100 |

| 2 | 200 |

| 3 | 300 |

| 4 | 400 |

| 5 | 100 |

| 6 | 200 |

| 7 | 300 |

| 8 | 400 |

| 9 | 100 |

| 10 | 200 |

| 11 | 300 |

| 12 | 400 |

| 13 | 100 |

| 14 | 200 |

| 15 | 300 |

| 16 | 400 |

| 17 | 100 |

| 18 | 200 |

| 19 | 300 |

+----+--------+

19 rows in set (0.00 sec)

mysql> select * from product_details;

+----+--------+-------+

| id | weight | exist |

+----+--------+-------+

| 2 | 22 | 0 |

| 4 | 44 | 1 |

| 5 | 55 | 0 |

| 6 | 66 | 1 |

| 23 | 25 | 30 |

+----+--------+-------+

5 rows in set (0.00 sec)

mysql> select * from product1 left join product_details on product1.id=product_details.id;

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 2 | 200 | 2 | 22 | 0 |

| 4 | 400 | 4 | 44 | 1 |

| 5 | 100 | 5 | 55 | 0 |

| 6 | 200 | 6 | 66 | 1 |

| 1 | 100 | NULL | NULL | NULL |

| 3 | 300 | NULL | NULL | NULL |

| 7 | 300 | NULL | NULL | NULL |

| 8 | 400 | NULL | NULL | NULL |

| 9 | 100 | NULL | NULL | NULL |

| 10 | 200 | NULL | NULL | NULL |

| 11 | 300 | NULL | NULL | NULL |

| 12 | 400 | NULL | NULL | NULL |

| 13 | 100 | NULL | NULL | NULL |

| 14 | 200 | NULL | NULL | NULL |

| 15 | 300 | NULL | NULL | NULL |

| 16 | 400 | NULL | NULL | NULL |

| 17 | 100 | NULL | NULL | NULL |

| 18 | 200 | NULL | NULL | NULL |

| 19 | 300 | NULL | NULL | NULL |

+----+--------+------+--------+-------+

19 rows in set (0.00 sec)



left join原理:

查看执行计划,驱动表为product1 ,首先全表扫描product1,得到product1的记录19条,然后全表扫描product_details,得到product_details的记录5条,然后再join buffer缓存里面join连接,取product1第一条;id=1那条与product_details的5条逐一比较,如果和5条都不相等,则将product1整条输出+product_details(所有列为NULL填充),如果相等则显示将product1整条+匹配的product_details行,依次循环。

mysql> select * from product1 left join product_details on product1.id=product_details.id and product1.id=11;

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 1 | 100 | NULL | NULL | NULL |

| 2 | 200 | NULL | NULL | NULL |

| 3 | 300 | NULL | NULL | NULL |

| 4 | 400 | NULL | NULL | NULL |

| 5 | 100 | NULL | NULL | NULL |

| 6 | 200 | NULL | NULL | NULL |

| 7 | 300 | NULL | NULL | NULL |

| 8 | 400 | NULL | NULL | NULL |

| 9 | 100 | NULL | NULL | NULL |

| 10 | 200 | NULL | NULL | NULL |

| 11 | 300 | NULL | NULL | NULL |

| 12 | 400 | NULL | NULL | NULL |

| 13 | 100 | NULL | NULL | NULL |

| 14 | 200 | NULL | NULL | NULL |

| 15 | 300 | NULL | NULL | NULL |

| 16 | 400 | NULL | NULL | NULL |

| 17 | 100 | NULL | NULL | NULL |

| 18 | 200 | NULL | NULL | NULL |

| 19 | 300 | NULL | NULL | NULL |

+----+--------+------+--------+-------+

19 rows in set (0.01 sec)

这个是在上面那条语句的基础上,判断下除了判断product1.id是否等于product_details。id外,还要判断product1.id是否等于11,等于的话,就输出product1的行+product_details的行,否则输出product1的行+product_details(NULL替换的行)

mysql> select * from product1 left join product_details on product1.id=11;

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 11 | 300 | 2 | 22 | 0 |

| 11 | 300 | 4 | 44 | 1 |

| 11 | 300 | 5 | 55 | 0 |

| 11 | 300 | 6 | 66 | 1 |

| 11 | 300 | 23 | 25 | 30 |

| 1 | 100 | NULL | NULL | NULL |

| 2 | 200 | NULL | NULL | NULL |

| 3 | 300 | NULL | NULL | NULL |

| 4 | 400 | NULL | NULL | NULL |

| 5 | 100 | NULL | NULL | NULL |

| 6 | 200 | NULL | NULL | NULL |

| 7 | 300 | NULL | NULL | NULL |

| 8 | 400 | NULL | NULL | NULL |

| 9 | 100 | NULL | NULL | NULL |

| 10 | 200 | NULL | NULL | NULL |

| 12 | 400 | NULL | NULL | NULL |

| 13 | 100 | NULL | NULL | NULL |

| 14 | 200 | NULL | NULL | NULL |

| 15 | 300 | NULL | NULL | NULL |

| 16 | 400 | NULL | NULL | NULL |

| 17 | 100 | NULL | NULL | NULL |

| 18 | 200 | NULL | NULL | NULL |

| 19 | 300 | NULL | NULL | NULL |

+----+--------+------+--------+-------+

23 rows in set (0.00 sec)



这条语句的执行计划是:全表扫描product1得到19行,全表扫描product_details得到5行,放入 join buffer中join。取product1第一条,在product_details的5行逐条连接,看是否product1.id=11,是的话输出改行数据,不是的话就输出product1.id行数据+product_details(NULL数据),依次循环。

mysql> select * from product1 left join product_details on product1.id=11 where product1.id=11;

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 11 | 300 | 2 | 22 | 0 |

| 11 | 300 | 4 | 44 | 1 |

| 11 | 300 | 5 | 55 | 0 |

| 11 | 300 | 6 | 66 | 1 |

| 11 | 300 | 23 | 25 | 30 |

+----+--------+------+--------+-------+

5 rows in set (0.00 sec)



这条语句执行计划解读:

mysql> create table t01 as select * from product1 where product1.id=11;

Query OK, 1 row affected (0.02 sec)

Records: 1 Duplicates: 0 Warnings: 0

mysql> select * from t01 left join product_details on t01.id=11;

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 11 | 300 | 2 | 22 | 0 |

| 11 | 300 | 4 | 44 | 1 |

| 11 | 300 | 5 | 55 | 0 |

| 11 | 300 | 6 | 66 | 1 |

| 11 | 300 | 23 | 25 | 30 |

+----+--------+------+--------+-------+

5 rows in set (0.00 sec)

从product1的索引 in_01中扫描获得product1.id=11所在的数据块,然后获取product1 where product1.id=11的行数据,该行数据再与product_details关联5次,并核实是否product1.id=11,是的话,输出product1行数据+product_details行数据,不相等就不输出product1行数据+product_details行(NULL)数据。而不是一些人所说的 where是对join
结果集的过滤。

mysql> select * from product1 left join product_details on product_details.id=6 where product1.id in(6,7);

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 6 | 200 | 6 | 66 | 1 |

| 7 | 300 | 6 | 66 | 1 |

+----+--------+------+--------+-------+

2 rows in set (0.00 sec)

mysql> select * from product1 left join product_details on product_details.id=11 where product1.id=11;

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 11 | 300 | NULL | NULL | NULL |

+----+--------+------+--------+-------+

1 row in set (0.00 sec)

mysql> select * from product1 left join product_details on product_details.id=11 where product1.id>11;

+----+--------+------+--------+-------+

| id | amount | id | weight | exist |

+----+--------+------+--------+-------+

| 12 | 400 | NULL | NULL | NULL |

| 13 | 100 | NULL | NULL | NULL |

| 14 | 200 | NULL | NULL | NULL |

| 15 | 300 | NULL | NULL | NULL |

| 16 | 400 | NULL | NULL | NULL |

| 17 | 100 | NULL | NULL | NULL |

| 18 | 200 | NULL | NULL | NULL |

| 19 | 300 | NULL | NULL | NULL |

+----+--------+------+--------+-------+

8 rows in set (0.00 sec)

上几条sql 都是一样的原理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: