如何将不同值合并为带编号的列组形式?
解决方案:将长格式成绩数据转换为宽格式
原始数据
| Name | Subject | Grade |
|---|---|---|
| Joe Bloggs | English | A |
| Joe Bloggs | Maths | B |
| Sam Smith | English | B |
| Sam Smith | Physics | C |
目标格式
| Name | Subject 1 | Grade 1 | Subject 2 | Grade 2 |
|---|---|---|---|---|
| Joe Bloggs | English | A | Maths | B |
| Sam Smith | English | B | Physics | C |
1. SQL 实现方案
方法1:条件聚合(通用兼容多数数据库)
先给每个学生的科目分配行号,再通过条件判断提取对应科目和成绩:
SELECT Name, MAX(CASE WHEN rn = 1 THEN Subject END) AS "Subject 1", MAX(CASE WHEN rn = 1 THEN Grade END) AS "Grade 1", MAX(CASE WHEN rn = 2 THEN Subject END) AS "Subject 2", MAX(CASE WHEN rn = 2 THEN Grade END) AS "Grade 2" FROM ( SELECT Name, Subject, Grade, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Subject) AS rn FROM your_table_name ) t GROUP BY Name;
方法2:PIVOT 语法(适用于SQL Server、Oracle等)
通过两次透视分别处理科目和成绩字段:
SELECT Name, [1] AS "Subject 1", [Grade_1] AS "Grade 1", [2] AS "Subject 2", [Grade_2] AS "Grade 2" FROM ( SELECT Name, Subject, Grade, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Subject) AS rn, 'Grade_' + CAST(ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Subject) AS VARCHAR) AS grade_rn FROM your_table_name ) t PIVOT ( MAX(Subject) FOR rn IN ([1], [2]) ) p1 PIVOT ( MAX(Grade) FOR grade_rn IN ([Grade_1], [Grade_2]) ) p2;
2. Excel/Google Sheets 实现方案
方法1:透视表法
- 添加序号列:在原始数据旁新增列
rn,输入公式=COUNTIF($A$2:A2,A2)并下拉,得到每个学生的科目序号(1、2...)。 - 插入透视表:将
Name拖到「行」,rn拖到「列」,Subject和Grade拖到「值」(值字段设置为「最大值」,因为每个序号对应唯一值)。 - 调整列标题为
Subject 1、Grade 1等,整理格式即可。
方法2:XLOOKUP 函数法
假设目标表A列是唯一姓名,在B2单元格输入:=XLOOKUP($A2&"_"&1, $A$2:$A$5&"_"&$D$2:$D$5, $B$2:$B$5)
C2单元格输入:=XLOOKUP($A2&"_"&1, $A$2:$A$5&"_"&$D$2:$D$5, $C$2:$C$5)
D2、E2单元格将公式中的1替换为2,下拉填充即可(D列为新增的序号列)。
3. Python Pandas 实现方案
利用分组序号+透视功能快速转换:
import pandas as pd # 构造原始数据 df = pd.DataFrame({ 'Name': ['Joe Bloggs', 'Joe Bloggs', 'Sam Smith', 'Sam Smith'], 'Subject': ['English', 'Maths', 'English', 'Physics'], 'Grade': ['A', 'B', 'B', 'C'] }) # 生成每个学生的科目序号 df['rn'] = df.groupby('Name').cumcount() + 1 # 透视转换为宽格式 wide_df = df.pivot(index='Name', columns='rn', values=['Subject', 'Grade']) # 重命名列名 wide_df.columns = [f'{col[0]} {col[1]}' for col in wide_df.columns] wide_df = wide_df.reset_index() print(wide_df)
内容的提问来源于stack exchange,提问作者Jonathon Quinn
相关产品推荐
相关产品推荐

