我有一个查询,相对较慢。我试图多次重写它,但我找不到更好的解决方案。所以我想问你,如果它从一开始就以错误的方式写成,那就没问题。
SELECT sql_calc_found_rows
present_id, present_id, present_url, present_name, present_text_short, foto_name, price_id, price_price, price_amount, price_dis
FROM a_present
LEFT JOIN
(SELECT price_id, price_present_id, price_supplier_id, price_dis, price_amount,
(CASE WHEN price_dis <> 0 THEN price_dis ELSE price_amount END) as price_price
FROM a_price
WHERE
price_visibility = 1 AND price_deleted <> 1
GROUP BY price_id ) pri
ON pri.price_present_id = present_id
LEFT JOIN _present_fotos ON foto_id = present_title_foto
LEFT JOIN _cate_pres ON cp_present = present_id
WHERE present_visibility = 1 AND present_deleted <> 1 AND price_price > 0 AND present_out <> 1 AND cp_category IN (30,31,232,32)
GROUP BY present_id
ORDER BY price_price
LIMIT 8
描述:price_dis是折扣后的价格,price_amount是折扣前的价格..每个产品(现在)的价格都比一个更多..是否有更快的解决方案来选择最终价格?
如果你发现桌面结构不好,我会遇到麻烦:)
非常感谢!
编辑: explain select
答案 0 :(得分:0)
好的,所以我看到了一些可以改进的事情。
首先,您正在使用从子查询派生的表来加入 - 使用子查询MySQL不使用索引(因此减速)。不要使用子查询加入,而是尝试使用表a_price
本身加入,并将CASE
语句放在原始(父)SELECT
中。它应该允许MySQL在JOINing时使用索引,并且当子查询返回许多行时非常重要。
它应该看起来像这样(包括MIN()
和GROUP BY
,因为您需要最低价格):
SELECT (...), price_amount, price_dis, MIN((CASE WHEN pri.price_dis <> 0 THEN pri.price_dis ELSE pri.price_amount END)) as price_price
FROM a_present
LEFT JOIN a_price pri
ON pri.price_present_id = present_id AND price_visibility = 1 AND price_deleted <> 1
(...)
GROUP BY present_id
其次 - 如EXPLAIN SELECT
所示 - MySQL不使用表_cate_pres
上的索引。你应该使用索引加入JOIN并选择你需要的类别(因为你把它们中的一些放在IN (..)
语句中)。
尝试在_cate_pres.cp_category
上添加索引,和/或在此表上添加复合索引(使用两列 - cp_category和cp_present)。
通常,您希望实现的结果(并非总是可行,但在您的情况下我非常确定),是让{@ 1}}中的以下内容消失: