SQL实现:分组内按指定规则筛选单条记录并同步主记录Code值
解决方案
这里有一套能完美匹配你需求的SQL方案,我会拆解逻辑,确保每一步都贴合你给出的规则:
完整SQL代码
WITH group_primary AS ( SELECT "Group", Code AS primary_code, Status AS primary_status, Name AS primary_name FROM your_table WHERE Code > 0 ), ranked_candidates AS ( SELECT t.*, gp.primary_code, gp.primary_status, CASE WHEN t.Name = gp.primary_name THEN 1 ELSE 0 END AS is_primary, CASE WHEN gp.primary_status = 'active' THEN CASE WHEN is_primary = 1 THEN 1 ELSE 99 END ELSE CASE WHEN is_primary = 1 THEN 99 ELSE CASE t.Status WHEN 'active' THEN 1 WHEN 'pre_active' THEN 2 WHEN 'pending' THEN 3 WHEN 'inactive' THEN 4 ELSE 5 END END END AS priority, ROW_NUMBER() OVER () AS row_id FROM your_table t JOIN group_primary gp ON t."Group" = gp."Group" ), selected_records AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY "Group" ORDER BY priority ASC, row_id ASC ) AS rn FROM ranked_candidates ) SELECT Name, CASE WHEN Code = 0 THEN primary_code ELSE Code END AS Code, Status, "Group" FROM selected_records WHERE rn = 1;
逻辑拆解
group_primaryCTE:先锁定每个分组的主记录(也就是Code>0的那条,你已经保证每个组都有),保存它的关键信息,用来后续判断和Code替换。ranked_candidatesCTE:- 给原始表加上
row_id行号,确保相同优先级的记录能选中原始顺序靠前的(对应规则4); - 标记每条记录是否是主记录;
- 按规则计算优先级:
- 如果主记录是
active状态,只有主记录的优先级设为1,其他记录优先级设为99(这样只会选中主记录,符合规则2); - 如果主记录不是
active状态,直接把主记录的优先级设为99(排除它,符合规则3的“从组内其他记录筛选”要求),其他记录按照active > pre_active > pending > inactive的优先级赋值。
- 如果主记录是
- 给原始表加上
selected_recordsCTE:对每个分组,按优先级升序、行号升序排序,取第一条(rn=1),这就是该分组符合要求的唯一记录。- 最终查询:如果选中的记录
Code=0,就用主记录的Code替换它(符合规则3),然后输出结果。
注意事项
- 如果使用MySQL,需要把双引号包裹的
"Group"换成反引号`Group`(因为Group是SQL关键字); - 行号
row_id的生成在部分数据库中可能需要调整,比如MySQL可以用变量生成:SELECT *, @row_num := @row_num + 1 AS row_id FROM your_table, (SELECT @row_num := 0) AS init - 该方案基于你给出的规则1(每个分组必然有且仅有一条
Code>0的记录),如果实际场景中有多个Code>0的记录,需要额外调整主记录的筛选逻辑。
结果验证
用你提供的测试数据运行后,会得到完全符合期望的结果:
| Name | Code | Status | Group |
|---|---|---|---|
| Allen | 8 | active | A |
| Sarah | 2 | pre_active | B |
内容的提问来源于stack exchange,提问作者Aaron Lee
相关产品推荐
相关产品推荐

