表值参数为空时如何实现INNER JOIN并返回TOP 1000条结果
解决方案
方案1:静态条件JOIN写法
适合参数少、数据量不大的场景,无需拼接SQL:
SELECT DISTINCT TOP (1000) Person.col1, Person.col2 FROM dbo.Person INNER JOIN @tbl1 t1 ON Person.col3 = t1.val OR NOT EXISTS (SELECT 1 FROM @tbl1) INNER JOIN @tbl2 t2 ON Person.col4 = t2.val OR NOT EXISTS (SELECT 1 FROM @tbl2) INNER JOIN @tbl3 t3 ON Person.col5 = t3.val OR NOT EXISTS (SELECT 1 FROM @tbl3)
- 优点:写法简单,为固定静态SQL,无需处理动态拼接逻辑
- 缺点:OR条件会影响索引命中率,大数据量场景下性能不如动态SQL方案
方案2:动态SQL拼接(推荐)
适配大数据量场景,执行计划最优,完全避免冗余条件:
DECLARE @sql NVARCHAR(MAX) = N' SELECT DISTINCT TOP (1000) Person.col1, Person.col2 FROM dbo.Person ' -- 仅当表值参数存在数据时拼接对应INNER JOIN语句 IF EXISTS (SELECT 1 FROM @tbl1) SET @sql += N'INNER JOIN @tbl1 t1 ON Person.col3 = t1.val ' IF EXISTS (SELECT 1 FROM @tbl2) SET @sql += N'INNER JOIN @tbl2 t2 ON Person.col4 = t2.val ' IF EXISTS (SELECT 1 FROM @tbl3) SET @sql += N'INNER JOIN @tbl3 t3 ON Person.col5 = t3.val ' -- 执行动态SQL,传入表值参数 EXEC sp_executesql @sql, N'@tbl1 [你的表值参数类型名] READONLY, @tbl2 [你的表值参数类型名] READONLY, @tbl3 [你的表值参数类型名] READONLY', @tbl1 = @tbl1, @tbl2 = @tbl2, @tbl3 = @tbl3
- 优点:生成的SQL无任何冗余判断,执行计划最优,可避免全表扫描,快速返回TOP 1000结果,完全不会产生NULL值数据
- 缺点:需要自行替换代码中的
[你的表值参数类型名]为实际创建的表值参数类型的名称
注意事项
- 两种方案均符合需求:无数据的表值参数不会触发匹配逻辑,也不会返回携带NULL的结果
- 如果业务场景数据量极大,优先选择动态SQL方案,性能优势更明显
内容的提问来源于stack exchange,提问作者Richard Watts
相关产品推荐
相关产品推荐

