2012-06-12 102 views
0

因此,我正在嘗試編寫一個MySQL查詢,以用三個單獨的查詢替換目前正在使用PHP進行的操作。我有一個只有兩個值的類別表:一個ID和一個名稱。還有另外兩個表,每個表都有一個引用第一個表中ID的外鍵。我需要從Categories表中獲取所有值的列表,以及每個其他兩個表中每個值的引用次數。我可以準確地從各個第二表的使用每個單獨的查詢得到計數:MySQL多個左連接導致不正確的計數值

SELECT nga_calevir_event_categories.*, COUNT(nga_calevir_events.event_id) AS event_total 
FROM nga_calevir_event_categories 
LEFT JOIN (nga_calevir_events) 
ON nga_calevir_event_categories.id = nga_calevir_events.event_category 
GROUP BY nga_calevir_event_categories.id; 

SELECT nga_calevir_event_categories.*, COUNT(nga_usermeta.user_id) AS member_total 
FROM nga_calevir_event_categories 
LEFT JOIN (nga_usermeta) 
ON (nga_usermeta.meta_value = nga_calevir_event_categories.id 
AND nga_usermeta.meta_key = 'category_id') 
GROUP BY nga_calevir_event_categories.id; 

然而,當我嘗試這些查詢它開始給兩個不正確的結果結合起來計數。這是聯合查詢:

SELECT nga_calevir_event_categories.*, 
COUNT(nga_calevir_events.event_id) AS event_total, 
COUNT(nga_usermeta.user_id) AS member_total 
FROM nga_calevir_event_categories 
LEFT JOIN (nga_calevir_events) 
ON nga_calevir_event_categories.id = nga_calevir_events.event_category 
LEFT JOIN (nga_usermeta) 
ON (nga_usermeta.meta_value = nga_calevir_event_categories.id 
AND nga_usermeta.meta_key = 'category_id') 
GROUP BY nga_calevir_event_categories.id; 

它似乎是第一行的計數加倍。我一直在試驗這個幾個小時,現在我無法弄清楚。有任何想法嗎?如果您需要更多信息來幫助我,請告訴我。

回答

0

這不起作用,因爲連接是組合:

SELECT nga_calevir_event_categories.*, 
COUNT(nga_calevir_events.event_id) AS event_total, 
COUNT(nga_usermeta.user_id) AS member_total 


FROM nga_calevir_event_categories 
LEFT JOIN (nga_calevir_events) 
ON nga_calevir_event_categories.id = nga_calevir_events.event_category 
-- The above is almost the same as an inner join, so long as every 
-- category has at least one event. 

LEFT JOIN (nga_usermeta) 
ON (nga_usermeta.meta_value = nga_calevir_event_categories.id 
AND nga_usermeta.meta_key = 'category_id') 
-- This is where you're going to get weird. This is going to join 
-- every row already figured out- basically, a row for every event 
-- with every usermeta that matches! 


GROUP BY nga_calevir_event_categories.id; 

這確實是二查詢 - 有加盟usermeta到類別沒有理智的方式(除非我誤解了應用程序)。不過,有一種方法可以將它放入一個SQL語句中。試試這個:

SELECT categories.*, 
     coalesce(event_hits.hits, 0) + coalesce(meta_hits.hits, 0) as total_hits 
FROM nga_calevir_event_categories as categories  

LEFT JOIN 
(select event_category as catid, count(*) as hits 
    FROM (nga_calevir_events) 
    group by event_category 
) as event_hits ON event_hits.catid = categories.id 

LEFT JOIN (
    select meta_value as catid, count(*) as hits 
    FROM nga_usermeta 
    WHERE meta_key = 'category_id' 
    group by meta_value 
) as meta_hits ON meta_hits.catid = categories.id 

這裏使用兩個內選擇獲取用於各兩個表的類別ID的計數,然後加入那些內選擇實際的類別,並總結他們各自返回的計數。我們使用COALESCE來確保在其中一個表中沒有用處的情況下,假定爲0。

希望這會有所幫助!