首页 > 解决方案 > 使用交叉应用子查询优化 sql 查询的问题

问题描述

所以我有三张桌子:

MakerParts,包含车辆零件的主要信息:

ID 制造商 ID 零件号 描述
1 1 ABC1234
2 1 XYZ1234

MakerPrices,它保存了零件的价格历史变化(参考文献MakerParts.IdMakerPartNumberId表格MakerPriceUpdatesUpdateId

ID 制造商零件编号 ID 更新 ID 价格
1 1 1 9.83
2 1 2 11.23

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

ID 日期 文件名
1 2019-01-09 00:00:00.000 临时文件
2 2019-01-11 00:00:00.000 temp2.​​csv

这意味着一个零件 (MakerParts) 可能有多个价格 (MakerPrices)。价格变化的日期在 MakerPricesUpdates 表上。

我想选择最近价格为零的所有 MakerParts,按 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 没有建议新的索引):

在此处输入图像描述

标签: sqlperformancequery-optimization

解决方案


尝试:

WITH tab AS (
    SELECT *, NULL as Price FROM MakerParts
    WHERE not exists ( 
        SELECT Id
        FROM MakerPrices
        WHERE MakerPrices.MakerPartNumberId = MakerParts.Id 
    )  
)

SELECT * from tab WHERE MakerId = 2
UNION ALL
SELECT a.* , Price
FROM [dbo].[MakerParts] a
    LEFT JOIN [dbo].[MakerPrices] b
    ON b.MakerPartNumberId = a.Id
WHERE MakerId = 2 AND Price = 0

推荐阅读