如何在SQL中为每个WeekGroup动态添加10%的额外行?
为临时表每个WeekGroup分组动态增加10%的额外行
我来帮你解决这个问题,你需要给#Appointments临时表中每个WeekGroup分组的Vacant状态行添加10%的额外行,这里提供两种可行方案,一种是更高效的集合式SQL实现,另一种是贴合你原有思路的循环方法:
方法1:基于集合的高效实现(推荐)
SQL是面向集合的语言,这种方法不需要循环,通过CTE先计算每个分组需要添加的行数,再生成对应额外行并与原数据合并,性能更好。
-- 计算每个WeekGroup的Vacant行数及需添加的10%行数(取整) WITH GroupRowCounts AS ( SELECT WeekGroup, COUNT(*) AS TotalVacantRows, ROUND(COUNT(*) * 0.1, 0) AS RowsToAdd FROM #Appointments WHERE AppointmentStatus = 'Vacant' GROUP BY WeekGroup ), -- 为每个分组生成对应数量的额外行 ExtraRows AS ( SELECT grc.WeekGroup, nums.n AS RowNum FROM GroupRowCounts grc -- 利用系统表生成足够多的行号,适配任意分组的行数需求 CROSS JOIN (SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n FROM sys.all_columns) nums WHERE nums.n <= grc.RowsToAdd ) -- 合并原数据与额外行,按分组排序并让额外行位于分组末尾 SELECT CustomerNo, AppointmentDate, AppointmentStatus, WeekGroup FROM #Appointments WHERE AppointmentStatus = 'Vacant' UNION ALL SELECT '' AS CustomerNo, NULL AS AppointmentDate, '10% extra row' AS AppointmentStatus, WeekGroup FROM ExtraRows ORDER BY WeekGroup, AppointmentStatus DESC;
关键说明:
GroupRowCounts:精准统计每个分组的有效行数,并计算出需要添加的10%行数(自动取整)。ExtraRows:通过交叉连接系统表生成行号,快速创建对应数量的额外行,避免手动循环。- 最终排序确保每个分组的原始数据在前,额外行在后,符合你期望的结果格式。
方法2:循环实现(贴合你原有的代码逻辑)
如果你更习惯用循环逐个处理分组,这个方案和你原来的代码思路一致,通过游标遍历所有WeekGroup并分别处理:
-- 创建用于存储最终结果的临时表 CREATE TABLE #ResultsTable ( CustomerNo NVARCHAR(20), AppointmentDate DATE, AppointmentStatus NVARCHAR(100), WeekGroup INT ); -- 声明所需变量 DECLARE @CurrentWeekGroup INT; DECLARE @GroupTotalRows INT; DECLARE @RowsToAdd INT; -- 创建游标获取所有需要处理的WeekGroup DECLARE WeekGroupCursor CURSOR FOR SELECT DISTINCT WeekGroup FROM #Appointments WHERE AppointmentStatus = 'Vacant' ORDER BY WeekGroup; -- 打开游标开始遍历 OPEN WeekGroupCursor; FETCH NEXT FROM WeekGroupCursor INTO @CurrentWeekGroup; WHILE @@FETCH_STATUS = 0 BEGIN -- 统计当前分组的Vacant行数 SELECT @GroupTotalRows = COUNT(*) FROM #Appointments WHERE AppointmentStatus = 'Vacant' AND WeekGroup = @CurrentWeekGroup; -- 计算需要添加的10%行数(取整) SET @RowsToAdd = ROUND(@GroupTotalRows * 0.1, 0); -- 插入当前分组的原始数据 INSERT INTO #ResultsTable(CustomerNo, AppointmentDate, AppointmentStatus, WeekGroup) SELECT CustomerNo, AppointmentDate, AppointmentStatus, WeekGroup FROM #Appointments WHERE AppointmentStatus = 'Vacant' AND WeekGroup = @CurrentWeekGroup; -- 循环插入对应的额外行 WHILE @RowsToAdd > 0 BEGIN INSERT INTO #ResultsTable VALUES ('', NULL, '10% extra row', @CurrentWeekGroup); SET @RowsToAdd = @RowsToAdd - 1; END -- 移动到下一个WeekGroup FETCH NEXT FROM WeekGroupCursor INTO @CurrentWeekGroup; END -- 关闭并释放游标资源 CLOSE WeekGroupCursor; DEALLOCATE WeekGroupCursor; -- 查询最终结果 SELECT * FROM #ResultsTable ORDER BY WeekGroup, AppointmentStatus DESC;
关键说明:
- 游标会遍历所有存在
Vacant行的WeekGroup,确保每个分组都被处理。 - 每个分组单独计算需要添加的行数,完全复用了你原来的10%取整逻辑。
- 额外行用
'10% extra row'标记,和你期望的结果格式一致。
内容的提问来源于stack exchange,提问作者jk1844
相关产品推荐
相关产品推荐

