如何根据表格子列的顺序字符串值设置条件行号
按分组生成循环递增的条件行号
原数据
| col | sub_col |
|---|---|
| A | A |
| A | B |
| A | C |
| A | A |
| A | B |
| A | C |
| B | A |
| B | B |
| B | B |
| B | C |
| B | A |
| B | B |
| B | B |
| B | C |
目标结果
| col | sub_col | order_by_sub_col |
|---|---|---|
| A | A | 0 |
| A | B | 1 |
| A | C | 2 |
| A | A | 0 |
| A | B | 1 |
| A | C | 2 |
| B | A | 0 |
| B | B | 1 |
| B | B | 2 |
| B | C | 3 |
| B | A | 0 |
| B | B | 1 |
| B | B | 2 |
| B | C | 3 |
解决方案
核心思路是按col分组,先识别每个循环的起始点(即sub_col='A'的行),给每个循环分配唯一组ID,再在循环组内生成从0开始的递增编号。
支持窗口函数的数据库(PostgreSQL、MySQL 8.0+、SQL Server等)
SELECT col, sub_col, ROW_NUMBER() OVER (PARTITION BY col, cycle_id ORDER BY (SELECT NULL)) - 1 AS order_by_sub_col FROM ( SELECT col, sub_col, -- 按col分组,累加标记循环起始点,生成循环ID SUM(CASE WHEN sub_col = 'A' THEN 1 ELSE 0 END) OVER (PARTITION BY col ORDER BY (SELECT NULL)) AS cycle_id FROM your_table ) t -- 保持原数据顺序 ORDER BY col, cycle_id, order_by_sub_col;
说明
- 内层查询通过
SUM() OVER()窗口函数,按col分组、行顺序累加,遇到sub_col='A'时加1,同一循环内的行共享相同的cycle_id。 - 外层查询用
ROW_NUMBER()在col+cycle_id分组内生成行号,减1后得到从0开始的编号。 ORDER BY (SELECT NULL)用于保留原表行顺序,若有明确的排序字段可替换为实际字段。
MySQL 5.x(无窗口函数)实现
SET @prev_col = ''; SET @row_num = -1; SELECT col, sub_col, @row_num := CASE WHEN col != @prev_col OR sub_col = 'A' THEN 0 ELSE @row_num + 1 END AS order_by_sub_col, @prev_col := col FROM your_table ORDER BY col, (SELECT NULL) HAVING order_by_sub_col IS NOT NULL;
内容的提问来源于stack exchange,提问作者AlexeyPrikhodko
相关产品推荐
相关产品推荐

