sql - 使用交叉应用子查询优化sql查询时出现问题

标签 sql performance query-optimization

所以我有三个表:

MakerParts,保存车辆零件的主要信息:

<表类=“s-表”> <标题> ID MakerId 零件编号 描述 <正文> 1 1 ABC1234 轮胎 2 1 XYZ1234 门

MakerPrices ,它保存零件的价格历史变化(MakerParts.Id 上的引用 MakerPartNumberId ,以及 MakerPriceUpdates 上的表 UpdateId ):

<表类=“s-表”> <标题> ID MakerPartNumberId 更新ID 价格 <正文> 1 1 1 9.83 2 1 2 11.23

MakerPriceUpdates ,保存价格更新的日期。此更新基本上是上传到我们系统的 CSV 文件。一个文件,这个表一行,表上多个价格变动MakerPrices .

<表类=“s-表”> <标题> ID 日期 文件名 <正文> 1 2019-01-09 00:00:00.000 临时.csv 2 2019-01-11 00:00:00.000 temp2.​​csv

这意味着一个零件 (MakerParts) 可能有多个价格 (MakerPrices)。价格更改的日期位于 MakerPricesUpdates 表中。

我想要选择最新价格为零的所有 MakerPart,并按表 MakerParts 上的 MakerId 进行过滤。

我尝试过的:

select mp.* from MakerParts mp cross apply
    (select top 1 Price from MakerPrices inner join 
        MakerPricesUpdates on MakerPricesUpdates.Id = MakerPrices.UpdateId where 
        MakerPrices.MakerPartNumberId = mp.Id order by Date desc) as p
where mp.MakerId = 1 and p.Price = 0

但这速度慢得离谱(MakerPrices 表上有大约 1 亿行)。我很难优化这个查询。 (结果只有两行 MakerId 1,并且运行了 2 分钟)。我也尝试过:

select * from (
    select 
        mp.*,
        (select top 1 Price from MakerPrices inner join 
        MakerPricesUpdates on MakerPricesUpdates.Id = MakerPrices.UpdateId 
        where MakerPrices.MakerPartNumberId = mp.Id order by Date desc) as Price
    from MakerParts mp) as temp
where temp.Price = 0 and MakerId = 1

相同的结果,相同的时间。我的查询计划(第一个查询)(Management Studio 没有建议新索引):

enter image description here

最佳答案

我认为您可以避免将 MakerPriceUpdatesmakerprices 一起加入,因为具有最高的 UpdateId您可以找到最新的价格更新。这会节省您一些时间。

select mp.* from MakerParts mp cross apply
    (select top 1 Price from MakerPrices where 
        MakerPrices.MakerPartNumberId = mp.Id order by MakerPrices.UpdateId desc) as p
where mp.MakerId = 1 and p.Price = 0

您可以通过避免使用 cte 和 row_number() 进行排序和排序来进一步减少一些时间,如下所示:

;with LatestMakerPrices as
(
    select  *,row_number()over(partition by MakerPartNumberId order by updateid desc)rn from MakerPrices 
)
select mp.* from MakerParts mp cross apply
    (select price from LatestMakerPrices lmp where lmp.MakerPartNumberId=mp.Id) as p
where mp.MakerId = 1 and p.Price = 0

有问题的查询和我的答案之间的执行计划差异: enter image description here

关于sql - 使用交叉应用子查询优化sql查询时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66882021/

相关文章:

sql - 如何删除每个日期都有重复值的记录

sql - 如何在 Oracle 中将 NUMBER 转换为 VARCHAR2?

sql - 如何在 CASE 中执行 SELECT 语句

mysql - 给定用例的最佳 MySQL 表模式

mysql - 简单的内连接和索引

mysql - 在JDO中定义基于哈希的索引

java - Java中有没有办法让事件带有变量?里面的例子

node.js - 专业人员如何处理数千、数十万甚至数百万个 JSON 对象? Node .js

mysql - 大量的 MySQL 临时磁盘表

mysql - mysql从多个表中获取数据,逗号分隔