如何理解SQL里的Join操作
表和表之间的联接,即join操作是SQL里很重要的操作之一。理解了联接,就能有效地关联关系型数据。
Join操作一共分为3种:
1. 交叉联接
这是所有联接中最基础也是必须执行的第一个步骤,SQL语法称为cross join
。
假设A表有m条数据,m = 2
AId | Name |
---|---|
1 | Red |
2 | Blue |
B表有n条数据,n = 2
BId | RGB |
---|---|
2 | 00FF00 |
3 | FFFF00 |
那么A表和B表进行交叉连接后,一共会产生m * n条,本例为4条数据。
AId | Name | BId | RGB |
---|---|---|---|
1 | Red | 2 | 00FF00 |
1 | Red | 3 | FFFF00 |
2 | Blue | 2 | 00FF00 |
2 | Blue | 3 | FFFF00 |
这就是我们常说的笛卡尔积。要联接的两表的行数越多,笛卡尔积的结果集也就越大。
2. 内联接
交叉联接将所有的组合可能性都考虑到了,并汇集到了一个结果集里。内联接就是操作这个结果集,筛选出满足联接条件的行。SQL语法称为inner join
。
假设前面的例子,要筛选出满足A表的AId等于B表的BId的行,SQL写法为
1 | select A.*, B.* |
这里的A.AId = B.BId
就是联接条件,当有联接条件时必须加上on
谓词。如果还有其它联接条件只要用and
连接即可。结果为
AId | Name | BId | RGB |
---|---|---|---|
2 | Blue | 2 | 00FF00 |
换句话说,内联接就是起过滤行的作用,过滤的对象是满足过滤条件的由交叉连接产生的结果集。
3. 左(右)联接
左联接比起内联接来,区别只多出了一个步骤,在内联接的基础之上补充左表被内联接过滤掉的那些行,右表的行的数据以NULL替代。什么意思,用上面的例子来解释,A表左联接B表,筛选条件为AId = BId,SQL写法为
1 | select A.*, B.* |
结果
AId | Name | BId | RGB |
---|---|---|---|
2 | Blue | 2 | 00FF00 |
1 | Red | NULL | NULL |
A(左)表AId为1的行,原本是不满足过滤条件的,也就是被内联接过滤掉的行,但是左联接会将左表被内联接过滤掉的行,添加到结果集的最后,右表的数据则用NULL替代。
换句话说,左表会返回所有行,不满足联接条件的右表返回NULL。
右联接(right join
)以及全联接(full join
)原理同左联接。
总结
为什么我要写下这篇文章,因为工作的时候,使用左联接查询,以为返回的结果集行数就应该等于左表的行数。后来才发现我忘了交叉连接的存在,如果联接条件是一对多的话,左联接产生的结果集行数大于左表的行数。也是提醒自己,不要忘了交叉联接的存在,它是所有联接的基础。
为什么我要写这篇文章,原因是因为一开始理解左联接的时候,容易被左表返回所有行