基于重复值添加唯一标识符的MS-SQL实现需求
实现MS-SQL分组标识需求的解决方案
嘿,我来帮你搞定这个MS-SQL的分组标识需求!先把需求细节和实现方案理清楚:
需求背景
你手里的表片段长这样(每行对应产品生命周期的一个新阶段):
| Market | Cycle | Milestone | Sale |
|---|---|---|---|
| A | NULL | NULL | NULL |
| A | 1 | NULL | NULL |
| B | NULL | NULL | NULL |
| B | 3 | 4 | NULL |
| B | 3 | 4 | 5 |
| A | 1 | 2 | NULL |
| A | 1 | 2 | 1 |
| NULL | C | 6 | 7 |
| NULL | C | NULL | NULL |
| D | 8 | NULL | NULL |
| D | 8 | 9 | NULL |
需要给每行加上唯一的Group标识,预期输出如下:
| Market | Cycle | Milestone | Sale | Group |
|---|---|---|---|---|
| A | NULL | NULL | NULL | 1 |
| A | 1 | NULL | NULL | 1 |
| B | NULL | NULL | NULL | 2 |
| B | 3 | 4 | NULL | 2 |
| B | 3 | 4 | 5 | 2 |
| A | 1 | 2 | NULL | 1 |
| A | 1 | 2 | 1 | 1 |
| NULL | C | 6 | 7 | 3 |
| NULL | C | NULL | NULL | 3 |
| D | 8 | NULL | NULL | 4 |
| D | 8 | 9 | NULL | 4 |
补充规则要注意
- 新增的
Market为"D"的行,统一归到Group 1; - 新增的
Market为NULL且Cycle是新值的行,会启动一个新组(比如组5),后续同Cycle值的行都归到这个新组里。
解决方案代码
直接上可以用的MS-SQL代码,记得把YourTableName替换成你实际的表名:
WITH GroupSeed AS ( -- 先给每行生成分组核心标识:优先用非空的Market,Market空就用Cycle SELECT *, CASE WHEN Market IS NOT NULL THEN Market ELSE Cycle END AS GroupKey, -- 标记每个GroupKey的首次出现行,用来生成分组映射 ROW_NUMBER() OVER (PARTITION BY CASE WHEN Market IS NOT NULL THEN Market ELSE Cycle END ORDER BY (SELECT NULL)) AS RowNum FROM YourTableName ), GroupMapping AS ( -- 给每个唯一的GroupKey分配分组编号,同时处理D归为Group1的特殊规则 SELECT GroupKey, CASE WHEN GroupKey = 'D' THEN 1 ELSE DENSE_RANK() OVER (ORDER BY CASE WHEN GroupKey = 'D' THEN 0 ELSE 1 END, GroupKey) END AS GroupId FROM GroupSeed WHERE RowNum = 1 -- 只取每个GroupKey的第一行来生成编号 ) -- 关联原表和分组映射,得到最终结果 SELECT t.Market, t.Cycle, t.Milestone, t.Sale, gm.GroupId AS [Group] FROM YourTableName t JOIN GroupSeed gs ON t.Market = gs.Market AND t.Cycle = gs.Cycle AND t.Milestone = gs.Milestone AND t.Sale = gs.Sale JOIN GroupMapping gm ON gs.GroupKey = gm.GroupKey ORDER BY [Group]; -- 可以根据你的需求调整排序逻辑
代码逻辑拆解
我给你把代码的逻辑拆解开,方便你理解和调整:
GroupSeed CTE:
- 生成
GroupKey:这是分组的核心依据,优先用非空的Market,如果Market是空的就用Cycle值; - 用
ROW_NUMBER()给每个GroupKey的行编号,标记出每个分组的第一行,后续用来生成唯一的分组编号。
- 生成
GroupMapping CTE:
- 基于每个
GroupKey的第一行,给它们分配唯一的分组ID; - 单独处理
D的情况,直接把它的分组ID设为1; - 其他
GroupKey用DENSE_RANK()生成连续的编号,确保分组号是连续不重复的。
- 基于每个
最终查询:
- 把原表和分组映射关联起来,给每行加上对应的分组编号;
- 最后按分组排序,让结果更清晰,你也可以根据实际需求修改排序方式。
补充规则适配说明
- 新增的
Market='D'行:因为GroupKey是'D',会被直接映射到Group1,符合你的要求; - 新增的
Market为NULL且Cycle是新值的行:会生成新的GroupKey,DENSE_RANK()会自动给它分配下一个连续的分组号(比如组5),后续同Cycle的行都会关联到这个分组。
内容的提问来源于stack exchange,提问作者Y-O
相关产品推荐
相关产品推荐

