MySQL中为动态变化的重复姓名(忽略大小写)分配统一ID的方法
MySQL动态生成忽略大小写的重复姓名统一ID方案
没问题,针对你这个动态生成忽略大小写重复姓名统一ID的需求,我给你两种在MySQL里的实现方案,完全不用依赖静态的CASE语句,适配数据动态变化的场景:
方案一:使用窗口函数(MySQL 8.0+ 推荐)
如果你的MySQL版本是8.0及以上,直接用DENSE_RANK()窗口函数就能简洁实现,核心思路是先把姓名统一转成小写(或大写),再基于这个标准化后的字段生成连续的唯一ID:
SELECT i, j, DENSE_RANK() OVER (ORDER BY LOWER(i)) AS k FROM your_table_name;
原理说明
LOWER(i)将姓名列的所有值转为小写,消除大小写差异,让kathy和Kathy被视为同一分组DENSE_RANK()会按照标准化后的姓名排序,为每个唯一分组分配连续的ID,新添加的姓名会自动获得对应的新ID,完全适配动态数据场景
方案二:使用自定义变量(兼容MySQL 5.x版本)
如果你的MySQL版本较低,不支持窗口函数,可以用自定义变量来实现同样的效果:
SELECT t.i, t.j, @rank := IF(@prev_name = LOWER(t.i), @rank, @rank + 1) AS k, @prev_name := LOWER(t.i) FROM ( -- 先按标准化后的姓名排序,保证同姓名的记录连续 SELECT i, j FROM your_table_name ORDER BY LOWER(i) ) t, -- 初始化变量:@rank记录当前ID,@prev_name记录上一条的标准化姓名 (SELECT @rank := 0, @prev_name := '') r;
原理说明
- 子查询先将原表按小写后的姓名排序,确保相同姓名(忽略大小写)的记录连续排列
- 自定义变量
@rank用来维护当前的ID值,@prev_name记录上一条记录的标准化姓名 - 每遍历一条记录,判断当前姓名的小写是否和上一条相同:相同则保持ID不变,不同则ID加1,同时更新
@prev_name的值
验证结果
用你提供的测试数据执行上述任意一种方案,都会得到你期望的输出:
| i | j | k |
|---|---|---|
| kathy | 25 | 1 |
| Kathy | 45 | 1 |
| Jason | 34 | 2 |
| James | 67 | 3 |
| Kathy | 37 | 1 |
| Emily | 56 | 4 |
| Jason | 34 | 2 |
内容的提问来源于stack exchange,提问作者Rachel jones




