So I am trying to write a single MySQL query to replace what is currently being done in PHP with three separate queries. I have a table for Categories with only two values: an ID and a Name. There are two other tables which each have a foreign key referring to the ID from the first table. I need to get a list of all the values from the Categories table as well as a count of how many times each value is referenced in each of the two other tables. I can get the count accurately from each of the second tables using a separate query for each:
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;
and
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;
However, when I try to combine these queries it starts giving incorrect results for both counts. Here is the combined query:
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;
It seems to be doubling the count for the first row. I’ve been experimenting with this for a couple hours now and I just can’t figure it out. Any ideas? Let me know if you need more information to help me with this.
This doesn’t work because joins are combinatorial:
This really is two queries- there’s no sane way to join usermeta to categories (unless I misunderstand the application). There is a way to get it into one SQL statement, though. Try this:
This uses two inner selects to get a count of category ids used for each of the two tables, then joins those inner selects to the actual categories, and sums the counts they each returned. We use COALESCE to make sure that where there were no uses in one of the tables, 0 is assumed.
Hope this helps!