mysql left join分析

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 都是一样的原理

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值