SQL查询优化:从SALE_LINE表取唯一币种否则返回默认值的方案
销售行币种判断SQL优化方案
原有代码问题说明
你的原始可运行SQL对SALE_LINE表执行了多次扫描,嵌套多层子查询,数据量较大时IO开销会非常高,所以性能表现不佳。而你后续修改的简化SQL错误是因为添加了GROUP BY SL.Currency后会按币种分组返回多行结果,变量只会被赋值为最后一行的计算结果,完全不符合需求逻辑。
优化方案
优化核心思路是仅扫描1次SALE_LINE表完成判断,用更高效的聚合逻辑替代COUNT(DISTINCT)和嵌套子查询:
- 当所有行的币种完全相同时,
MIN(Currency)和MAX(Currency)的返回值一定相等,直接取该值即可 - 当存在多个不同币种时,上述两个聚合返回值不同,直接返回默认值
- 表变量添加主键、用JOIN替代IN匹配,进一步提升执行效率
优化后代码如下:
DECLARE @salesLineIds VARCHAR(MAX), @defaultCurrency VARCHAR(10), @uniqueCurrency VARCHAR(10) SET @salesLineIds = '1,2,3'; SET @defaultCurrency = 'DOL'; -- 修正原代码遗漏的@变量前缀 -- 表变量添加主键,提升ID匹配效率 DECLARE @ID_LIST table (Id BIGINT PRIMARY KEY) INSERT INTO @ID_LIST SELECT TRY_CAST(value AS BIGINT) FROM STRING_SPLIT(@salesLineIds, ',') WHERE TRY_CAST(value AS BIGINT) IS NOT NULL -- 过滤无效ID避免匹配错误 -- 仅扫描一次SALE_LINE表完成计算 SELECT @uniqueCurrency = CASE WHEN MIN(SL.Currency) = MAX(SL.Currency) THEN MIN(SL.Currency) ELSE @defaultCurrency END FROM SALE_LINE SL INNER JOIN @ID_LIST IL ON SL.Id = IL.Id
额外性能优化建议
如果该查询执行频率较高,可以给SALE_LINE表创建覆盖索引,避免查询时回表查询数据,性能会有进一步提升:
CREATE NONCLUSTERED INDEX IX_SALE_LINE_Id_INCLUDE_Currency ON SALE_LINE (Id) INCLUDE (Currency)
内容的提问来源于stack exchange,提问作者refresh
相关产品推荐
相关产品推荐

