2016-08-19 55 views
2

我已閱讀placing conditions in WHERE or in JOIN does not matter。但是,我遇到了一個聽起來有點可疑的結果:結果根據我的情況而有所不同。任何人都可以向我解釋它的基本邏輯嗎?當條件放置在WHERE或LEFT JOIN中時,爲什麼COUNT中的「零」結果出現?

我有兩個虛擬表話題問題。一個問題有一個標題和一個與主題的關係1-n,以便每個問題都與一個主題相關。然後,該問題的題目可以跨主題重複。它的結構非常糟糕,但我無法改變它:/

所有這一切都是in SQL Fiddle

<topic>     <issues> 

id | name   id | topic_id | title 
------------   --------------------- 
1 | art   1 |  1 | final 
2 | music   2 |  1 | semi final 
3 | sport   3 |  2 | final 
         4 |  2 | draft 

現在我想選擇一個主題中有多少次出現在問題的列表,獲取用於時候有沒有一個0。使用LEFT JOIN使得它,用How to include 「zero」/「0」 results in COUNT aggregate?幫助:

SELECT 
    t.name, count(i.title) 
FROM 
    topic as t 
LEFT JOIN issues as i 
    ON t.id = i.topic_id 
GROUP BY t.id; 

這將返回預期的結果:

name | count 
-------------- 
art | 2 
music | 2 
sport | 0 

現在我想知道一個給定標題橫跨主題出現了多少次。例如,每個主題發生了多少次「最終」?這裏是顯示問題出在哪裏:

SELECT 
    t.name, count(i.title) 
FROM 
    topic as t 
LEFT JOIN issues as i 
    ON t.id = i.topic_id 
     AND i.title = "final" -- in the LEFT JOIN! 
GROUP BY t.id; 

返回:

name | count 
-------------- 
art | 1 
music | 1 
sport | 0     -- yeah, sport - 0 is here 

SELECT 
    t.name, count(i.title) 
FROM 
    topic as t 
LEFT JOIN issues as i 
    ON t.id = i.topic_id 
WHERE 
    i.title = "final"   -- in the WHERE! 
GROUP BY t.id; 

返回

name | count 
-------------- 
art | 1 
music | 1     -- where is sport - 0? 
+6

左連接與條件使其內連接,並將確保連接表有數據,而進行聚合。 –

+0

@AbhikChakraborty說。您可以嘗試使用WHERE(i.title IS NULL或i.title =「final」) – ipeiro

+1

確切地說,只有WHERE條件涉及右列表中的LEFT JOIN中的列纔有效地使其成爲INNER。 – Serg

回答

1

這只是不正確的「將條件放在WHERE或JOIN無關緊要」。如果一個FROM在頂層只有內部JOIN(INNER JOIN ON,JOIN ON,CROSS JOIN),那麼你可以在它的內部JOIN和WHERE之間移動條件。但是對於OUTER JOIN來說,情況並非如此。請參閱CROSS JOIN vs INNER JOIN in SQL Server 2008重新連接和Conditions in LEFT JOIN (OUTER JOIN) vs INNER JOIN重新連接外部&連接在一起。

一個OUTER JOIN ON返回INNER JOIN ON返回的內容,加上可能有更多行通過NULL來擴展輸入行。如果稍後通過WHERE條件刪除那些額外的行,則可以使用INNER JOIN ON(with或)而不使用WHERE條件,或者只使用WHERE條件的CROSS JOIN。

CROSS JOIN進行參數表的交叉連接,(INNER)JOIN ON做一個CROSS JOIN,然後刪除不滿足條件的行,並且一個外部JOIN ON進行INNER JOIN ON,然後按照LEFT/RIGHT/FULL添加了由NULL擴展的行在失敗條件下形成的某些行。然後,在所有聯合WHERE刪除行失敗的條件之後。然後SELECT刪除,添加和重命名列。

+0

Uhms,有趣。這讓我想知道:執行了'LEFT JOIN'之後,是否評估了WHERE條件? – fedorqui

+0

如果您不知道在FROM中的所有連接之後應用了WHERE,那麼您不理解SQL的某些絕對基本知識。你讀過這個答案中的鏈接嗎?我已經添加了一個關於SELECT如何工作的段落。 – philipxy

+0

@fedorqui你最近編輯了這個答案。感謝您的關注。如果您認爲我的答案會因內容更改而得到改善,請發表評論。 (切斷的句子是準確的(關鍵)建設性的。) – philipxy

1

嘗試移動,因爲這其中左條件JOIN如果使用左連接表的在這個條件下會像內柱JOIN,將只返回匹配的記錄

SELECT 
    t.name, count(i.title) 
FROM 
    topic as t 
LEFT JOIN issues as i 
    ON t.id = i.topic_id AND i.title = "final"  
GROUP BY t.id; 
+0

很好的解釋!注意這個代碼已經在問題中了,我的奇想是結果不同的原因。 – fedorqui

+0

謝謝@fedorqui我在閱讀本文時忽略了它,但我認爲這將清除OP對WHERE子句中的LEFT JOIN的困惑 –

+0

是的,這解釋了爲什麼我的結果不同。謝謝! – fedorqui

3
WHERE 
    i.title = "final" 

也排除行,其中i.title is NULL。所以當LEFT JOIN在i表中沒有對應的值時,WHERE排除行。

WHERE 
    i.title = "final" or i.title is null 

離開行

+0

Uhms,有趣!所以'WHERE'條件超過了'LEFT JOIN'連接另一個表中的所有值? – fedorqui

+0

是的。首先連接表並創建連接行。然後應用WHERE的條件 – StanislavL

+0

@fedorqui「所以WHERE條件超過了LEFT JOIN加入另一個表中的所有值」是無法理解的。 – philipxy

2

正如評論所說,您的最終查詢這的確是一個內部聯接,與左連接數返回0,如果有左表中的不匹配,但是當你使用它成爲內部聯接的地方,只有在兩個表中匹配的情況下才返回結果。

/*Joins on the key values provided, if there is no value that 
corresponds on the left table counts returns 0 */ 

select t.name, count(i.title) 
from topic as t 
left join issues as i on t.id = i.topic_id 
group by t.id; 

select t.name, count(i.title) 
from topic as t 
left join issues as i on t.id = i.topic_id 
and i.title = "final" 
group by t.id; 

/*Joins on the key values provided, if there is no value that corresponds on the left 
table then count returns 0 and then filter by the title 
    */ 
select t.name, count(i.title) 
from topic as t 
left join issues as i on t.id = i.topic_id 
where i.title = "final" 
group by t.id; 

/*Solution*/ 
select t.name, count(i.title) 
from topic as t 
left join issues as i on t.id = i.topic_id 
where (i.title = "final" || i.title is null) 
group by t.id; 
+0

非常感謝您給予的解答。現在我更清楚在那裏發生了什麼。但是,不是很奇怪,一個美麗的LEFT JOIN如何成爲INNER JOIN? :D – fedorqui

+0

不客氣,歡迎我的朋友。 –

+0

@philipxy我沒有這麼說。再次檢查我的評論。 – fedorqui

相關問題