簡體   English   中英

MySQL加入+子查詢混淆

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM