下面的查询是获取有关一类玩具的一些信息,并显示三种情况(例如,全新、二手、翻新)的最新销售价格。每次出售的价格几乎总是不同的。还有一件事-sales表的行id不一定按时间顺序排列,例如sale id为5的玩具可能比sale id为10的玩具发生得晚。
此查询可以工作,但无法执行。它在一个可控的时间内运行,通常是1秒左右。但是,我需要添加另一个左连接以包含更多的数据,这会导致查询时间膨胀到大约9秒,而不是bueno。
以下是正在运行但未执行的查询:
SELECT b.brand_name, t.toy_id, t.toy_name, t.toy_number, tt.toy_type_name, cp.catalog_product_id, s.date_sold, s.condition_id, s.sold_price FROM brands AS b
LEFT JOIN toys AS t ON t.brand_id = b.brand_id
JOIN toy_types AS tt ON t.toy_type_id = tt.toy_type_id
LEFT JOIN catalog_products AS cp ON cp.toy_id = t.toy_id
LEFT JOIN toy_category AS tc ON tc.toy_category_id = t.toy_category_id
LEFT JOIN (
SELECT date_sold, sold_price, catalog_product_id, condition_id
FROM sales
WHERE invalid = 0 AND condition_id <= 3
ORDER BY date_sold DESC
) AS s ON s.catalog_product_id = cp.catalog_product_id
WHERE tc.toy_category_id = 1
GROUP BY t.toy_id, s.condition_id
ORDER BY t.toy_id ASC, s.condition_id ASC
但就像我说的,很慢。sales表有大约20万行。
我试图做的是创建子查询作为视图,例如。,
CREATE VIEW sales_view AS
SELECT date_sold, sold_price, catalog_product_id, condition_id
FROM sales
WHERE invalid = 0 AND condition_id <= 3
ORDER BY date_sold DESC
然后用视图替换子查询,如
SELECT b.brand_name, t.toy_id, t.toy_name, t.toy_number, tt.toy_type_name, cp.catalog_product_id, s.date_sold, s.condition_id, s.sold_price FROM brands AS b
LEFT JOIN toys AS t ON t.brand_id = b.brand_id
JOIN toy_types AS tt ON t.toy_type_id = tt.toy_type_id
LEFT JOIN catalog_products AS cp ON cp.toy_id = t.toy_id
LEFT JOIN toy_category AS tc ON tc.toy_category_id = t.toy_category_id
LEFT JOIN sales_view AS s ON s.catalog_product_id = cp.catalog_product_id
WHERE tc.toy_category_id = 1
GROUP BY t.toy_id, s.condition_id
ORDER BY t.toy_id ASC, s.condition_id ASC
不幸的是,此更改导致查询不再获取最新的销售,并且它返回的销售价格也不再是最新的。
为什么表视图不返回与子查询相同的select相同的结果?
在阅读了几乎所有的 top-n-per-group
stackoverflow的问题和博客文章,我可以找到,得到一个真正有效的查询是美妙的。但是现在我需要将查询扩展一步,我遇到了性能问题。如果有人想回避上述问题,提供一些优化原始查询的方法,我洗耳恭听!
谢谢你的帮助。
1条答案
按热度按时间pu3pd22g1#
子查询性能问题的解决方案是使用这里提供的答案:groupwise maximum
我认为这种方法只能在查询单个表时使用,但实际上,即使您已经连接了许多其他表,它也可以工作。只需使用
s.date_sold < s2.date_sold
连接条件,并确保where子句在第二个表的id列中查找空值。