SQL必知必会:自连接(深入浅出自连接的原理与实现)
先来看代码:
SELECT cust_id,cust_name,cust_contact
FROM Customers
WHERE cust_name=(SELECT cust_name
FROM Customers
WHERE cust_contact="jack")
自连接是很让人困惑不解的!
因为: 结构及其简单,但是逻辑极其复杂!!
困惑源自理解,如果理解的方式和方法都没错,那就该调整理解的对象和方向了
困惑不可怕,可怕的是困惑的时候失去冷静
互联网的知识是互联的,所以完全不要花时间纠结和困惑于一家之言,
最好把家家户户都叫过来,七嘴八舌的都讨论一下就清楚了!
给不情愿一个说法,一个理由,就可以让不情愿变成情愿了
这条sql想干嘛?
所查询的字段都在Customers表中啊
根据cust_name查询cust_id,cust_name,cust_contact
是这样:
如果是只是要求:查询cust_id,cust_name,cust_contact,(无条件查询)
如果是要求:按cust_contact查询cust_id,cust_name,cust_contact(有条件查询)
如果是要求:按cust_name查询cust_id,cust_name,cust_contact(有条件查询)
查询分为有条件的,和无条件的
但是,还是不知道这条sql要干嘛啊?
这样,我做一个比较吧(能力就是表现为能,为什么能,他自己也不知道,但他就是能)
但是我们知道
很诡异啊?
如果字段都是一对一的会怎样呢?
如果字段不是一对一的又会是怎样呢?
如果没有任何关系只是随机的又会怎么样呢?
记事本的复制会连同空格一块复制的
SELECT cust_id,cust_name,cust_contact
FROM Customers
WHERE cust_name=(SELECT cust_name
FROM Customers
WHERE cust_contact="Jim Jones")SELECT cust_id,cust_name,cust_contact
FROM Customers
WHERE cust_contact="Jim Jones"
这两条sql的结果不是相同的么?
这不是多此一举么?
为什么看不懂这个sql?
因为对这个诡异的顾客表不了解!!!!
他得是一个什么样的表,居然需要自连接啊?
需要诡异的自连接的表
想必也是一张诡异的表吧
来对这个顾客表进行一点点的分析:
我们把这样表作为第一张表:
cust_id | cust_name | cust_contact |
100001 | fun4all | jack |
100002 | fun4all | tom |
100003 | fun5all | lucy |
100004 | fun5all | limi |
100005 | fun6all | ruby |
100006 | fun6all | harry |
100007 | fun7all | potter |
100008 | fun7all | tomas |
假定还有一张表也是这样:作为第二张表
cust_id | cust_name | cust_contact |
100001 | fun4all | jack |
100002 | fun4all | tom |
100003 | fun5all | lucy |
100004 | fun5all | limi |
100005 | fun6all | ruby |
100006 | fun6all | harry |
100007 | fun7all | potter |
100008 | fun7all | tomas |
如果仅仅是把这张表视为就是这张表的话,
看到这个表之后,我们都清楚那条sql为什么那么做了!
在仅仅知道cust_contact的情况下
要获得所有的cust_id
似乎不得不这么做.....
我们再看另外一种方式:
假定还有一张一模一样的表,
我们还可以这么做:
1.将两表求笛卡尔
2.按cust_name进行筛选(同表联结按谁筛选都要想好的)
也就是说
3.按cust_name进行整合,那么结果为:
100001 fun4all jack 100001 fun4all jack
100001 fun4all jack 100001 fun4all tom
100002 fun4all tom 100001 fun4all jack
100002 fun4all tom 100001 fun4all tom
4.最后我们按照第二个表的jack进行筛选就行了
我们都知道什么是自连接,但都不知道为什么是自连接!!
如果可以把两件事情连在一起做,就不要一次只做一件事情
但是如果两件事情可以连在一起,那么必须有可以连接的部分,例如榫和卯
分析下,做的这件事事情可以和那件事情串起来做,让这里做的事情所产生的影响可以发挥到下次事情中,
或者只是简简单单的缩短时间
我们把上面的步骤用下面的代码来实现:
必要时,也可缩进两格来表示子句的关系:
将其命名为代码2:
SELECT a.cust_id,a.cust_name,a.cust_contact
FROM Customers a,Customers b
WHERE a.cust_name = b.cust_name
AND b.cust_contact= "jack"
那么回头再来看看代码1:
SELECT cust_id,cust_name,cust_contact
FROM Customers
WHERE cust_name=(SELECT cust_name
FROM Customers
WHERE cust_contact="jack")
发现:两者的输出结果完全一样啊
但是代码1远远没有代码2好啊.....
为什么用两个代码表示呢?
这种情况就可以这么来应对:
代码1用来理解
代码2用来解决
理解了之后,那么什么样的解决都无法再困惑你了!
当要实现代码1的诉求时,我们就用代码去解决!!
不用子查询的,好吧!!