SQL Server按3/2/1循环规则合并三表的高效SELECT查询问询
高效实现循环取数的集合式SQL方案
之前用游标+存储过程的方式确实容易因为逐行处理导致性能瓶颈,我给你一个纯集合操作的解决方案,完全不需要循环逻辑,性能会提升很多!
核心思路
我们可以给每个表的记录分配批次号和优先级:
- 对TableA,每3条记录划分为一个批次(按ID排序)
- 对TableB,每2条记录划分为一个批次
- 对TableC,每1条记录划分为一个批次
然后按批次号排序,同一批次内优先取TableA的记录,再取TableB,最后TableC,这样就能实现「A3条→B2条→C1条」循环取数的效果。
完整SQL代码
WITH TableA_processed AS ( SELECT ID, FieldA, FieldB, FieldC, -- 选择你需要的字段 -- 计算批次号:每3条一个批次,用整数除法避免浮点运算 (ROW_NUMBER() OVER(ORDER BY ID) + 2) / 3 AS batch_num, -- 组内排序,保证同一批次内按原ID顺序 ROW_NUMBER() OVER(ORDER BY ID) AS group_row, -- 优先级:A最高,确保同一批次先取A的记录 1 AS priority FROM TableA ), TableB_processed AS ( SELECT ID, FieldA, FieldB, FieldC, -- 每2条一个批次 (ROW_NUMBER() OVER(ORDER BY ID) + 1) / 2 AS batch_num, ROW_NUMBER() OVER(ORDER BY ID) AS group_row, 2 AS priority FROM TableB ), TableC_processed AS ( SELECT ID, FieldA, FieldB, FieldC, -- 每1条一个批次,直接用行号作为批次号 ROW_NUMBER() OVER(ORDER BY ID) AS batch_num, ROW_NUMBER() OVER(ORDER BY ID) AS group_row, 3 AS priority FROM TableC ) SELECT ID, FieldA, FieldB, FieldC FROM ( SELECT * FROM TableA_processed UNION ALL SELECT * FROM TableB_processed UNION ALL SELECT * FROM TableC_processed ) AS combined_data ORDER BY batch_num, -- 按批次顺序循环 priority, -- 同一批次内先A、再B、最后C group_row; -- 组内保持原ID的排序
为什么这个方案更优?
- 纯集合操作:完全避免了游标逐行处理的开销,SQL Server的查询优化器可以高效处理这类基于窗口函数的查询,尤其是当
ID字段有聚集索引时,性能提升会非常明显。 - 自动跳过空表/已取完的表:如果某个表的数据已经取完(比如TableC只有5条记录),当批次号超过5时,该表不会产生对应的记录,
UNION ALL会自动跳过,完全符合你的需求。 - 灵活调整取数规则:如果后续需要修改每个表的取数数量(比如改成A取4条、B取3条),只需要调整批次号计算里的偏移量即可(比如A的
+2改成+3)。
小优化提示
如果你的ID字段是自增主键且有聚集索引,ROW_NUMBER() OVER(ORDER BY ID)的计算会非常高效,不需要额外的排序开销。
内容的提问来源于stack exchange,提问作者ISB
相关产品推荐
相关产品推荐

