如何在SQL Server 2008中基于logid列实现行转列(透视)
如何将长格式数据表转换为指定的宽格式?
这是个很常见的长表转宽表需求——把按logid和skillposition分散的行数据,合并成以logid为唯一标识的单行数据,同时用skillposition的值作为新列的后缀。我给你两种实用的实现方案,分别适配数据库操作和Python数据处理场景:
方案1:用SQL实现(以MySQL为例)
如果你的数据存在数据库里,用条件聚合是最直接的方式,逻辑清晰且性能稳定:
SELECT logid, -- 按skillposition提取对应的skilllevel,缺失时填充示例指定值 MAX(CASE WHEN skillposition = 1 THEN skilllevel ELSE 60 END) AS skilllevel1, MAX(CASE WHEN skillposition = 2 THEN skilllevel ELSE 20 END) AS skilllevel2, MAX(CASE WHEN skillposition = 3 THEN skilllevel ELSE 10 END) AS skilllevel3, -- 同理处理logonskill字段 MAX(CASE WHEN skillposition = 1 THEN logonskill ELSE 3 END) AS logonskill1, MAX(CASE WHEN skillposition = 2 THEN logonskill ELSE 5 END) AS logonskill2, MAX(CASE WHEN skillposition = 3 THEN logonskill ELSE 6 END) AS logonskill3 FROM your_table_name -- 替换成你的数据表名 GROUP BY logid;
小说明:
MAX()聚合函数是为了确保每个logid分组后只保留对应skillposition的唯一值(因为logid+skillposition应该是唯一组合,用MIN/SUM也能达到同样效果)- 如果你不需要固定填充缺失值,把
ELSE后面的数值改成ELSE NULL即可,缺失的位置会显示为空。
如果你用的是支持PIVOT语法的数据库(比如SQL Server、Oracle),可以用更简洁的PIVOT写法:
SQL Server版本示例:
SELECT logid, [1] AS skilllevel1, [2] AS skilllevel2, [3] AS skilllevel3, logonskill1, logonskill2, logonskill3 FROM ( SELECT logid, skilllevel, skillposition, logonskill, 'logonskill' + CAST(skillposition AS VARCHAR) AS logonskill_col FROM your_table_name ) AS src -- 第一次PIVOT处理skilllevel字段 PIVOT ( MAX(skilllevel) FOR skillposition IN ([1], [2], [3]) ) AS pvt_skill -- 第二次PIVOT处理logonskill字段 PIVOT ( MAX(logonskill) FOR logonskill_col IN ([logonskill1], [logonskill2], [logonskill3]) ) AS pvt_logon;
方案2:用Python Pandas实现
如果是用Python做数据处理,Pandas的pivot函数可以快速完成转换:
首先准备数据(如果是从文件/数据库读取,直接替换成读取逻辑即可):
import pandas as pd # 模拟你的样本数据 data = [ [101, 90, 1, 1], [101, 40, 2, 2], [102, 30, 4, 1] ] df = pd.DataFrame(data, columns=['logid', 'skilllevel', 'logonskill', 'skillposition'])
然后执行转宽操作:
# 分别对skilllevel和logonskill做透视 skilllevel_wide = df.pivot(index='logid', columns='skillposition', values='skilllevel') logonskill_wide = df.pivot(index='logid', columns='skillposition', values='logonskill') # 重命名列,加上对应后缀 skilllevel_wide.columns = [f'skilllevel{col}' for col in skilllevel_wide.columns] logonskill_wide.columns = [f'logonskill{col}' for col in logonskill_wide.columns] # 合并两个透视表,填充示例指定的缺失值 result = pd.concat([skilllevel_wide, logonskill_wide], axis=1).fillna({ 'skilllevel1': 30, 'skilllevel2':20, 'skilllevel3':10, 'logonskill1':4, 'logonskill2':5, 'logonskill3':6 }).reset_index() # 查看结果 print(result)
运行后就能得到你想要的格式:
logid skilllevel1 skilllevel2 skilllevel3 logonskill1 logonskill2 logonskill3 0 101 90.0 40.0 60.0 1.0 2.0 6.0 1 102 30.0 20.0 10.0 4.0 5.0 6.0
小说明:
- 如果不需要固定填充缺失值,去掉
fillna()部分即可,缺失的位置会显示为NaN - 如果你的
skillposition取值不止1-3,Pandas会自动识别所有存在的取值并生成对应列,不需要手动扩展。
内容的提问来源于stack exchange,提问作者Varun K
相关产品推荐
相关产品推荐

