我有一个包含过滤器的列表,我必须计算每个过滤器中有多少项,但是当设置了多个过滤器时,以下查询会变慢并且速度会慢得多
SELECT COUNT(*) FROM (
SELECT itf.`filter_id`
FROM `item_to_filter` AS `itf`
JOIN `item_to_inventory` AS `iti` ON (itf.`item_id` = iti.`item_id` AND iti.`quantity` > 0)
WHERE 1 = 1
AND (
(itf.`filter_group_id` = 2 AND itf.`filter_id` IN (1))
OR (itf.`filter_group_id` = 4 AND itf.`filter_id` IN (55)) //gets slower
OR (itf.`filter_group_id` = 1 AND itf.`filter_id` IN (107, 108)) //gets much slower
)
GROUP BY itf.`item_id`
HAVING COUNT(DISTINCT itf.`filter_group_id`) = 3
) AS `total_items`
还有其他方法可以编写查询来计算每个过滤器中的项目
在这里你可以看到表结构和数据(索引是否正确设置?)
答案 0 :(得分:1)
尝试这一个:将条件包装到UNION ALL子查询中。然后加入你的桌子。
SELECT COUNT(*) FROM (
SELECT itf.filter_id
FROM (
SELECT 2 as filter_group_id 1 as filter_id UNION ALL
SELECT 4 as filter_group_id 55 as filter_id UNION ALL
SELECT 1 as filter_group_id 107 as filter_id UNION ALL
SELECT 1 as filter_group_id 108 as filter_id
) f -- filters
JOIN item_to_filter AS itf USING(filter_group_id, filter_id)
JOIN item_to_inventory AS iti ON itf.item_id = iti.item_id
WHERE iti.quantity > 0
GROUP BY itf.item_id
HAVING COUNT(DISTINCT itf.filter_group_id) = 3
) AS total_items
您应该在item_to_filter(filter_group_id, filter_id)
上定义索引。但正如我在评论中写的那样,如果存在该索引,引擎可能会进行相同的优化。
为了更好地利用给定的索引,您可以将查询重写为
SELECT COUNT(*) FROM (
SELECT item_id
FROM item_to_inventory AS iti
JOIN item_to_filter AS itf2 USING(item_id) -- itf2: group_id = 2
JOIN item_to_filter AS itf4 USING(item_id) -- itf4: group_id = 4
JOIN item_to_filter AS itf1 USING(item_id) -- itf1: group_id = 1
WHERE iti.quantity > 0
AND itf2.filter_group_id = 2 AND itf2.filter_id IN (1)
AND itf4.filter_group_id = 4 AND itf4.filter_id IN (55)
AND itf1.filter_group_id = 1 AND itf1.filter_id IN (107,108)
) AS total_items
但即使在这里item_to_filter(filter_group_id, filter_id)
上的索引也应该提高效果。