[英]MySQL joins + sub-query confusion
我需要問一些關於連接真的令人困惑的事情
我的想法,我相信這曾經在過去對我有用,但似乎錯過了一些東西:
此查詢將生成兩個表中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)為什么第二種方法2A
給出了client_ids other then 1
結果,盡管在連接中單獨運行子查詢可以正常工作
3)如果不使用where子句, 2B
的子查詢是否會對來自父級的每條記錄執行?
4)如果我將1A查詢更改為,該怎么辦?
SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id AND client_modules.client_id = 1
剛剛刪除了客戶端表上的where子句,並將其放在子表的join子句中,這是有效的還是where子句?
問候
2a因為您使用了左連接 - 即左側的所有記錄,但只使用了右側的相關記錄,因此拉出了額外的客戶端。 你應該使用'完全加入'或'加入',而不是'左連接'。
不確定其他問題,但我的偏好是1B超過次選
編輯添加 - 要了解左連接發生了什么,請考慮其中的一個用途 - 哪些客戶端在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行的客戶端的記錄)
不,他們。 在我看來,我認為你不應該使用left join
。 你應該使用一個join
。 像老虎鉗一樣:
SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id
WHERE clients.client_id = 1;
這是更加嚴格的前進,你在where語句中限制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表的列中。 然后你可以這樣做:
SELECT *
FROM clients
WHERE EXISTS
(
SELECT
NULL
FROM
client_modules=1
AND client_moduless.client_id = clients.client_id
)
因此,如果您希望clients
表和client_modules
所有列都使用連接。 否則就去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
是一樣的。 這將導致大多數cretin導致相同的查詢計划。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.