MySQL多个左连接导致不正确的计数值

时间:2012-06-12 19:08:03

标签: mysql wordpress join count

所以我试图编写一个MySQL查询来用三个单独的查询替换当前在PHP中完成的操作。我有一个只有两个值的类别表:ID和名称。还有另外两个表,每个表都有一个外键,引用第一个表中的ID。我需要从Categories表中获取所有值的列表,以及在其他两个表中每个值引用的值的计数。我可以使用单独的查询从每个第二个表中准确地获取计数:

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;

似乎第一排的数量增加了一倍。我现在已经尝试了几个小时了,我无法理解。有任何想法吗?如果您需要更多信息来帮助我,请与我们联系。

1 个答案:

答案 0 :(得分: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。

希望这有帮助!