0

所以我正在尝试编写一个 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;

第一行的计数似乎增加了一倍。我已经对此进行了几个小时的试验,但我无法弄清楚。有任何想法吗?如果您需要更多信息来帮助我,请告诉我。

4

1 回答 1

1

这不起作用,因为连接是组合的:

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。

希望这可以帮助!

于 2012-06-14T22:47:17.957 回答