2012-06-08 30 views
6

我有一個左一個小問題,加入我想要設計的列表,並在每個設計我要顯示的每個設計多少意見都有。計數JOIN和WHERE

我用的是LEFT JOIN

SELECT ds.*, count(com.comment) AS countcom FROM tdic_designs ds 
LEFT JOIN tdic_comments com ON (com.design_id = ds.id) 
WHERE ds.approved = 1 AND ds.hidden = 0 AND com.approved = 1 
GROUP BY ds.id 
ORDER BY ds.date_added ASC 

但是,這並不工作,因爲它只會顯示一個設計,有1條評論,但我有表,其中第二設計沒有兩個設計發表評論。

如果我改變SQL來

SELECT ds.*, count(com.comment) AS countcom FROM tdic_designs ds 
LEFT JOIN tdic_comments com ON (com.design_id = ds.id) 
GROUP BY ds.id, com.approved, ds.approved 
ORDER BY ds.date_added ASC 

即去除WHERE子句。但這很糟糕,因爲它會選擇尚未批准的設計和評論。

什麼我想念/做錯了什麼?

+0

'MySQL',我相信? – Quassnoi

回答

8

繼續前行評論到ON條款的所有過濾器:

SELECT ds.*, COUNT(com.design_id) AS countcom 
FROM tdic_designs ds 
LEFT JOIN 
     tdic_comments com 
ON  com.design_id = ds.id 
     AND com.approved = 1 
WHERE ds.approved = 1 
     AND ds.hidden = 0 
GROUP BY 
     ds.id 
ORDER BY 
     ds.date_added ASC 
+0

工程就像一種享受!非常感謝! –

3

當您使用WHERE條款,這些限制都適用於由left join s的提供行。因此,如果某些行不符合限制條件,則會將其刪除。

你需要做的是將這些限制放在ON子句中,它應該起作用,所以如果它不起作用,它將顯示NULL而不是刪除行。

事情是這樣的:

SELECT ds.id, count(com.comment) AS countcom 
FROM tdic_designs ds 
LEFT JOIN tdic_comments com ON (com.design_id = ds.id) AND ds.approved = 1 AND ds.hidden = 0 AND com.approved = 1 
GROUP BY ds.id 
ORDER BY ds.date_added ASC 

的另一個問題是在使用SELECTds.*你只有在group BYds.id

+0

感謝這個:) –

+0

@MortenHagh沒有問題,如果它工作,不要忘了接受的答案:) –

0

問題是,當您在WHERE子句中包含com.approved = 1時,它會過濾掉com.approvedNULL的任何行 - 表示在外部表中找不到匹配的所有行。

正如其他人所建議的,您可以通過將該條件移至ON條款來解決此問題,但由於它不是連接條件,因此我不太喜歡這一點。

我會在外部表中的過濾器移動到內嵌視圖

SELECT ds.*, count(com.comment) AS countcom FROM tdic_designs ds 
LEFT JOIN (SELECT * FROM tdic_comments com WHERE com.approved = 1) com 
ON (com.design_id = ds.id) 
WHERE ds.approved = 1 AND ds.hidden = 0 
GROUP BY ds.id 
ORDER BY ds.date_added ASC 
+0

這對'MySQL'嚴重傷害的性能。 – Quassnoi

+0

@DaveCosta解決方案很差.. –

+0

@ aF.why?如果你的意思是出於同樣的原因,通過Quassnoi說,你可能是正確的,但問題並沒有指定的MySQL。在Oracle中,我不會指望有任何性能問題。 –