你如何优化这个半复杂的mysql查询?

时间:2012-09-27 12:15:09

标签: mysql

问候伙伴们!

这是db模式(简化为相关领域),以帮助说明我的难题:

enter image description here

  • 网上论坛有itemsitemsitem_options
  • 相同的item可以出现在多个categories
  • categoriesitemsitem_options都可以是有效或无效的(BOOL)。

类别看起来像这样(请注意parent_id嵌套,其中Fruit 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

我想要的是所有活动类别(id,parent_id和name)的快速列表,以及包含活动item_options的每个类别的活动项目的计数。

查询结果如下所示:

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

此查询有效,但需要~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;

下一个查询只需要约55毫秒,但无法包含顶级类别(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`;

任何人都会看到如何加快第一个查询,或修复第二个查询?

1 个答案:

答案 0 :(得分: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`
)
UNION
(
    SELECT c.`id`, c.`parent_id`, c.`name`, 0
    FROM `categories` AS c
    WHERE c.`parent_id` = 0
      AND c.`active` = 1
)
ORDER BY `parent_id`, `NAME`;

有人看到更好的方法吗? :d