MySQL View 代替子查询不返回相同的结果

Posted

技术标签:

【中文标题】MySQL View 代替子查询不返回相同的结果【英文标题】:MySQL View in place of subquery does not return the same result 【发布时间】:2020-10-24 17:57:50 【问题描述】:

下面的查询正在获取有关某个玩具类别的一些信息,并显示三个状况级别(例如,全新、二手、翻新)的最新销售价格。每次销售的价格几乎总是不同的。另一件事 - 销售表行 id 不一定按时间顺序排列,例如,销售 id 为 5 的玩具可能比销售 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 表有大约 200k 行。

我尝试将子查询创建为视图,例如,

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

很遗憾,此更改导致查询不再获取最近的销售,它返回的销售价格也不再是最近的。

为什么table view和子查询一样select返回的结果不一样?

在阅读了我能找到的几乎所有top-n-per-group *** 问题和博客文章之后,得到一个真正有效的查询真是太棒了。但是现在我需要将查询再扩展一步,我遇到了性能问题。如果有人想回避上述问题并提供一些优化原始查询的方法,我会全力以赴!

感谢所有帮助。

【问题讨论】:

在没有任何聚合函数的情况下,GROUP BY 子句永远不合适。剩下的就是噪音。 另外,只是为了观察,您在类别表上有一个外部联接,您似乎没有从中选择任何列。这似乎完全没有意义,除非我遗漏了什么。 @Kris 。 . .您的查询格式不正确。您在子查询中有一个 order by —— you 可能认为这会做一些有用的事情(它没有)。您的select 列与group by 不一致。我建议您提出一个新的问题,其中包含示例数据、期望的结果以及您想要完成的任务的解释。 请为每个案例提供EXPLAIN 【参考方案1】:

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

我认为这种方法只能在查询单个表时使用,但实际上即使在您连接了许多其他表时也可以使用。您只需使用s.date_sold &lt; s2.date_sold 连接条件将同一个表左连接两次,并确保 where 子句在第二个表的 id 列中查找空值。

【讨论】:

以上是关于MySQL View 代替子查询不返回相同的结果的主要内容,如果未能解决你的问题,请参考以下文章

如果子查询在 MySQL 中返回多于 1 行,如何将 JSON 放入列数据中

如果子查询没有返回结果,为啥“= ALL(子查询)”评估为真?

MYSQL基础九--子查询和连接

MySQL子查询(SubQuery)

MySQL在字段中使用select子查询(转)

Mysql数据库习题分析