Greetings fellow flowstackers!
Here’s the db schema (reduced to relevant fields) to help illustrate my conundrum:

- A webstore has
items, anditemshaveitem_options. - The same
itemcan appear in multiplecategories. categories,itemsanditem_optionscan all be active or inactive (BOOL).
Categories look like this (notice the parent_id nesting, where Fruit Seeds are inside of Seeds):
id parent_id name active
1 0 Seeds 1
2 1 Vegetable Seeds 1
3 1 Fruit Seeds 0
4 0 Plants 1
5 4 Vegetable Plants 1
6 4 Fruit Plants 1
What I want is a fast list of all active categories (id, parent_id and name), and the count of each category’s active items containing active item_options.
The query result would look like this:
id parent_id name item_count
1 0 Seeds 0
2 1 Vegetable Seeds 52
4 0 Plants 0
5 4 Vegetable Plants 103
6 4 Fruit Plants 79
This query works, but takes ~430ms:
SELECT c.`id`, c.`parent_id`, c.`name`,
(SELECT COUNT(*)
FROM `item_categories` AS ic
LEFT JOIN `items` AS i
ON (i.`id` = ic.`item_id`)
LEFT JOIN `item_options` AS io
ON (i.`id` = io.`item_id`)
WHERE c.`id` = ic.`category_id`
AND i.`active` = 1
AND io.`active` = 1
) AS `item_count`
FROM `categories` AS c
WHERE c.`active` = 1;
This next query takes only ~55ms, but fails to include the top-level categories (where parent_id = 0):
SELECT c.`id`, c.`parent_id`, c.`name`,
COUNT(ic.`item_id`) AS `item_count`
FROM `categories` AS c
LEFT JOIN `item_categories` AS ic
ON (c.`id` = ic.`category_id`)
LEFT JOIN `items` AS i
ON (i.`id` = ic.`item_id`)
LEFT JOIN `item_options` AS io
ON (i.`id` = io.`item_id`)
WHERE c.`active` = 1
AND i.`active` = 1
AND io.`active` = 1
GROUP BY c.`id`;
Anyone see how to speed up the first query, or fix the second one?
Oh! This seemed to do it …
Anyone see a better way? 😀