MySQL 替代子查询的视图与 return 不同的结果

MySQL View in place of subquery does not return the same result

下面的查询正在获取有关某类玩具的一些信息,并显示三个级别条件(例如,全新、二手、翻新)的最新销售价格。每次销售的价格几乎总是不同的。另一件事 - 销售 table 行 ID 不一定按时间顺序排列,例如,销售 ID 为 5 的玩具可能比销售 ID 为 10 的玩具晚发生。

此查询有效但性能不佳。它在可管理的时间内运行,通常约为 1 秒。但是,我需要添加另一个左连接以包含更多数据,这会导致查询时间激增至大约 9 秒,没有什么好。

这是有效但性能不佳的查询:

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

但是就像我说的那样它很慢。销售额 table 大约有 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

不幸的是,此更改导致查询不再抓取最近的销售,returns 的销售价格不再是最新的。

为什么 table 视图 return 与子查询 select 的结果不同?

在阅读了我能找到的几乎每个 top-n-per-group Whosebug 问题和博客文章之后,获得一个实际有效的查询真是太棒了。但现在我需要将查询再扩展一步,我 运行 陷入了性能问题。如果有人想回避上述问题并提供一些优化原始查询的方法,我洗耳恭听!

感谢所有帮助。

子查询性能问题的解决方案是使用此处提供的答案:Groupwise maximum

我认为这种方法只能在查询单个 table 时使用,但实际上它甚至在您加入许多其他 table 时也有效。您只需使用 s.date_sold < s2.date_sold 连接条件将相同的 table 左连接两次,并确保 where 子句在第二个 table 的 id 列中查找空值。