在SQL Server中按指定数量分组ID并生成组内编号与统计
按固定行数分组并生成组内编号、统计组内数量
需求说明
- 将
mytable中的记录按每组4条分组,最后一组允许不足4条 - 为每组内的行添加组内序号(RowNum)
- 统计每组包含的ID数量(IdCount)
原代码问题分析
你提供的代码存在几个语法和逻辑错误:
- 变量
@s不能直接搭配OVER子句,无法生成正确的分组ID (count Ids in each group)是无效语法,不能这样统计组内数量GROUP BY t.Id会将每条记录单独分组,违背了按4条一组的需求
正确实现方案
以下是基于SQL Server的可行代码,两种写法任选:
写法1:直接使用窗口函数
DECLARE @s INT = 4; SELECT Id, -- 计算分组ID:行号减1后除以每组行数,取整加1得到组号 ((ROW_NUMBER() OVER (ORDER BY Id ASC) - 1) / @s) + 1 AS GroupId, -- 生成组内序号:余数为0时取每组行数,否则取余数 CASE WHEN ROW_NUMBER() OVER (ORDER BY Id ASC) % @s = 0 THEN @s ELSE ROW_NUMBER() OVER (ORDER BY Id ASC) % @s END AS RowNum, -- 统计每组的记录数 COUNT(*) OVER (PARTITION BY ((ROW_NUMBER() OVER (ORDER BY Id ASC) - 1) / @s)) AS IdCount FROM mytable ORDER BY Id ASC;
写法2:用CTE优化重复计算
如果数据量较大,用CTE先计算全局行号,避免重复调用ROW_NUMBER(),提升效率:
DECLARE @s INT = 4; WITH RankedData AS ( SELECT Id, ROW_NUMBER() OVER (ORDER BY Id ASC) AS RowNumOverall FROM mytable ) SELECT Id, ((RowNumOverall - 1) / @s) + 1 AS GroupId, CASE WHEN RowNumOverall % @s = 0 THEN @s ELSE RowNumOverall % @s END AS RowNum, COUNT(*) OVER (PARTITION BY ((RowNumOverall - 1) / @s)) AS IdCount FROM RankedData ORDER BY Id ASC;
说明
- 分组ID的计算逻辑:行号从1开始,
(行号-1)/每组行数会将连续的N条记录归为同一组,加1后得到从1开始的组号 - 组内序号的逻辑和你原思路一致,确保每组的序号从1到4(最后一组不足4条时到实际数量)
COUNT(*) OVER (PARTITION BY 分组字段)用于按组统计该组的总记录数
内容的提问来源于stack exchange,提问作者Abohy
相关产品推荐
相关产品推荐

