2012-05-16 62 views
0

我需要問一些真正令人困惑關於加入MySQL的加入+子查詢混亂

我想什麼,我相信這爲我所用過去的工作,但好像是缺少了一些東西:

此查詢結果在兩個表中,其中的client_id爲1的數據 - 做工精細

/* gets data for one client_id*/ 

approach 1A 

SELECT * 
FROM clients LEFT JOIN client_modules 
       ON client_modules.client_id = clients.client_id 
WHERE clients.client_id = 1; 

現在,這種查詢是什麼,我認爲應該返回相同的結果,因爲,我已經使用子查詢中加入過濾結果第一即,已經從client_id 1的模塊獲取數據,但由於某種原因,它將給出其他client_ids數據作爲最終結果。

/* gets data for one client_id sub-query approach*/ 

approach 2A 

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
         FROM client_modules 
         WHERE client_modules.client_id = 1) 
      AS client_moduless ON client_moduless.client_id = clients.client_id; 



/* gets data for all client_ids */ 

approach 1B 

SELECT * FROM clients 
LEFT JOIN client_modules ON client_modules.client_id = clients.client_id; 



/* gets data for all client_ids*/ 

approach 2B 

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
         FROM client_modules) AS client_moduless 
       ON client_moduless.client_id = clients.client_id; 

問題:

1)哪種方法更有效當中xA and xB大數據量的使用?

2)爲什麼是第二個方法2Aclient_ids other then 1給出的結果,儘管運行子查詢中分別加入正常工作

3)將在2B子查詢,如果不使用執行從父每個記錄where子句?

4)如果我改變1A查詢

SELECT * FROM clients 
JOIN client_modules ON client_modules.client_id = clients.client_id AND client_modules.client_id = 1 

剛剛取消了對客戶表中的WHERE子句和推杆上的子表聯接子句中是這種高效或where子句?即從左側的所有記錄,但只能從右側相關的記錄 - 因爲你已經使用了左連接

問候

回答

1

沒有。在我看來,我認爲你不應該使用left join。你應該使用join。像老虎鉗:

SELECT * FROM clients 
JOIN client_modules ON client_modules.client_id = clients.client_id 
WHERE clients.client_id = 1; 

這是兩岸更向前,你是在哪裏聲明限制LEFT JOIN因此它具有相同的效果。

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
         FROM client_modules 
         WHERE client_modules.client_id = 1) 
      AS client_moduless ON client_moduless.client_id = clients.client_id; 

有了這個查詢,你將在客戶端表,併爲那些可以匹配client_moduless.client_id =返回所有行clients.client_id你將有一個該表。但是這不是一個限制JOIN它是一個左連接,這意味着當沒有值匹配時它返回null。子查詢將針對每一行運行。爲了獲得同樣的效果,你可以做這樣的:

SELECT * 
FROM clients JOIN (SELECT client_id, module_name 
         FROM client_modules 
         WHERE client_modules.client_id = 1) 
      AS client_moduless ON client_moduless.client_id = clients.client_id; 

現在,這將限制clients表,你只會得到已經在client_modules匹配的值。但我看不出有這樣一個觀點。相反,我會與海峽前鋒join一起前往。

這也取決於你對什麼感興趣。如果你只是在客戶表中的列。如果你希望所有從clients表中的列和client_modules去的加入讓

SELECT * 
FROM clients 
WHERE EXISTS 
(
    SELECT 
     NULL 
    FROM 
     client_modules=1 
     AND client_moduless.client_id = clients.client_id 
) 

:然後你就可以做到這一點。否則,用exists

編輯

去,我覺得這一點:

SELECT * FROM clients 
JOIN client_modules ON client_modules.client_id = clients.client_id 
AND client_modules.client_id = 1 

這:

SELECT * FROM clients 
JOIN client_modules ON client_modules.client_id = clients.client_id 
WHERE client_modules.client_id = 1 

是一樣的。這將使絕大多數的克萊汀產生相同的查詢計劃。

+0

用於識別'LEFT JOIN'我知道這一點,但這是我錯過了:),但是子查詢與直接連接表名有什麼關係?任何想法? – Junaid

+0

更新了答案 – Arion

+0

讚賞!請參閱更新後的問題 – Junaid

1

2A拉額外的客戶端。你應該使用'全連接'或'連接',而不是'左連接'。

不知道的其他問題,但我更傾向於將用於1B在子選擇

編輯補充 - 瞭解什麼用左發生的加入,考慮它的許多用途之一 - 其客戶不要」 t在client_modules中有沒有記錄?

人們很容易寫:

SELECT * FROM clients WHERE clientid NOT IN (select distinct(clientid) FROM client_modules) 

但是,下面可能是更有效的方法寫:

SELECT * FROM clients 
    LEFT JOIN client_modules ON clients.clientid = client_modules.clientid 
WHERE client_modules.clientid IS NULL 

(即只顯示來自客戶端無法連接到一個記錄client_module row)

+0

用於識別'LEFT JOIN'我知道這一點,但這是我想念的東西:),請你讓我知道不使用子選擇背後的原因是什麼? – Junaid

+0

TBH'個人偏好' - 我的直覺是在這種情況下的子查詢是沒有必要的,並且可能會更難以優化sql ...那說,我有時會發現一種最適合於一個數據集的方法可能效率較低和另外一個。問題是'速度夠快嗎?' (又名避免過早優化)如果不是,嘗試其他方法(可能包括添加其他索引),直到您獲得合理的性能。 –