1. 程式人生 > >SQL必知必會:自連線(深入淺出自連線的原理與實現)

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_name = "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的訴求時,我們就用程式碼去解決!!
不用子查詢的,好吧!!