2012-06-12 57 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。

希望这会有所帮助!