2016-05-12 100 views
0

這兩個查詢輸出不同的結果,
我有問題AND m.status = $1 ...每個條件跟着左連接表或移動到最後一部分,那就不同了吧?選擇左連接表使用條件

查詢1

SELECT count(mua.*) 
    AS total_row_count 
    FROM media_user_action mua 
    LEFT JOIN media m ON m.id = mua.media_id 
     AND m.status = $1 
    LEFT JOIN gallery_media gm ON gm.id = mua.media_id 
    LEFT JOIN gallery g ON g.id = gm.gallery_id 
     AND g.status = $1 
    LEFT JOIN "user" mcbu ON mcbu.id = m.create_by_user_id 
     AND mcbu.status = $1 
    LEFT JOIN "user" gcbu ON gcbu.id = g.create_by_user_id 
     AND gcbu.status = $1 
WHERE mua.user_id = $2 

查詢2

SELECT count(mua.*) 
    AS total_row_count 
    FROM media_user_action mua 
    LEFT JOIN media m ON m.id = mua.media_id 
    LEFT JOIN gallery_media gm ON gm.id = mua.media_id 
    LEFT JOIN gallery g ON g.id = gm.gallery_id 
    LEFT JOIN "user" mcbu ON mcbu.id = m.create_by_user_id 
    LEFT JOIN "user" gcbu ON gcbu.id = g.create_by_user_id 
WHERE 
m.status = $1 
AND g.status = $1 
AND mcbu.status = $1 
AND gcbu.status = $1 
AND mua.user_id = $2 

UPDATE
下面的答案

,如果我想確保返回結果,都必須與基礎/左連接表狀態都等於$ 1,(連接表recode可能爲空),所以我必須添加AND x.status ..按照連接表,對吧?

+1

您是在問「您應該使用哪兩個?」?因爲答案取決於你的意圖。 – Kritner

+0

感謝您的回覆,我想選擇每個相關的表,所有狀態都等於$ 1和mua.user_id = $ 2 – user1575921

回答

2

當您使用左外部聯接時,右表的值可能是NULL

爲了簡便起見,我們說我們有

Table A (id, name)Table B (fid, status)

然後QUERY1會像

select A.id, B.status 
from A 
left join (select * from B where status = $1) 
on A.id = B.fid; 

所以結果可能有B.status是NULL

而且QUERY2將會像

select C.* 
from (select A.id, B.status 
     from A 
     left join B 
     on A.id = B.fid 
) C 
where C.status = $1; 

這等於

select * 
from A 
inner join B 
on A.id = B.fid 
where B.status = $1; 

所以B.狀態必須是exactly是$ 1,並且從不是NULL

+0

謝謝你的例子,這是否意味着如果我想選擇/過濾A和B的狀態都等於1美元。如果B可能爲空,那麼我應該使用query1,如果B總是不爲空,那麼我也可以使用query2? – user1575921

+0

這取決於你的意圖。假設我們有一個人'A'。所有知道(** id **)'A'的朋友都很聰明(**狀態**)。現在1.你必須得到所有知道A的人的列表(一些朋友'A'知道 - NOT NULL',一些陌生人'A'不知道 - NULL')=> ** query1 **。 2.你必須得到所有知道'A'('not null')=> ** query2 **的朋友。 –

2

當您在LEFT JOIN -ed的表上放置WHERE條件,並且需要某些字段具有非空值時,則實際上將LEFT JOIN轉換爲INNER JOIN

這是因爲LEFT JOIN可能會在連接表沒有匹配記錄的情況下產生結果。在那種情況下,該「虛擬」記錄的所有字段值爲NULL。因此,通過要求其中一個字段不爲空,可以從結果中刪除這些實例。

如果恰恰相反,您將這樣的條件放在LEFT JOIN的條件下,那麼您不會破壞這種機制,即不匹配仍會給出結果,儘管有NULL

+0

感謝您的解釋,所以如果我確定連接表不是空的,那麼我可以把'和...'在最後或如果連接表可能爲空,那麼我應該把'和...'按照連接表正確的? – user1575921

+0

對。這就是來龍去脈。 – trincot

+0

如果我想要原始表只返回行(必須所有相關/左連接表列等於我所需或甚至爲空),那麼我應該把'和......'在最後的權利? (並且就像內部連接一樣) – user1575921

2

外連接意味着除了內連接之外,當找不到匹配時,所有列爲null的模擬記錄被連接。

因此,讓我們說一個mua我們沒有找到匹配的m。然後我們得到一個m記錄,其中所有列爲空。 m.status爲null。有了WHERE m.status = $1,你可以不記錄那條記錄,但是,所以你就是一個簡單的內連接。

外連接表的標準屬於ON子句。

+0

感謝您的解釋,所以如果我確定連接表不爲空,那麼我可以把'和...'放在最後,或者如果連接表可以爲空,那麼我應該把'和...'按照連接表右鍵? – user1575921

+0

現在的問題是:你想在結果中有mua記錄,但不存在任何具有所需狀態的m記錄嗎?如果沒有,那麼你不使用'LEFT [OUTER] JOIN',而是使用一個簡單的'[INNER] JOIN',在'WHERE'中是否有'm.status = $ 1'或者' ON'。如果是,則使用'LEFT [OUTER] JOIN'和條件屬於'ON'子句。 –

+0

如果其他連接表狀態不匹配我想要的或其他錶行不存在,但是如果m記錄存在,則必須使用左連接,然後輸出結果匹配數據結構。想要 – user1575921