行转列、列转行题目(收集中...)

本文介绍两种SQL数据转换方法:一种是使用MAX+DECODE+GROUP BY实现列转行;另一种是利用11g的新关键字PIVOT进行转换。此外,还提供了一种将多行数据合并为一行的方法。

一、列转行

1、把如下表

year  month amount
1991   1     1.1
1991   2     1.2
1991   3     1.3
1991   4     1.4
1992   1     2.1
1992   2     2.2
1992   3     2.3
1992   4     2.4
转换为结果表
year m1  m2  m3  m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4

方法(MAX+DECODE+GROUP BY):

with t as 
(
select 1991 as year, 1 as month,1.1 as amount from dual
union all
select 1991 as year, 2 as month,1.2 as amount from dual
union all
select 1991 as year, 3 as month,1.3 as amount from dual
union all
select 1991 as year, 4 as month,1.4 as amount from dual
union all
select 1992 as year, 1 as month,2.1 as amount from dual
union all
select 1992 as year, 2 as month,2.2 as amount from dual
union all
select 1992 as year, 3 as month,2.3 as amount from dual
union all
select 1992 as year, 4 as month,2.4 as amount from dual
)
select year, MAX(decode(month,1,amount,null)) m1,
MAX(decode(month,2,amount,null)) m2,
MAX(decode(month,3,amount,null)) m3,
MAX(decode(month,4,amount,null)) m4
from t
)
group by year


2. 使用11g的新关键字 pivot

with t as 
(
select 'aa' a,'b11' b, 1 n from dual
union all
select 'aa' a,'b22' b, 2 n from dual
union all
select 'aa' a,'b33' b, 3 n from dual
)
select * from t pivot(max(b) for n in(1 as b1,2 as b2,3 as b3 ));

结果:

A  B1  B2  B3
--  ---  ---  ---
aa b11 b22 b33



 二、多行转一行

select listagg(ename,',')
within group(order by empno desc)
from emp;


 

优化以下函数,追加输出要求再保存一份“变更文言.csv”到保存csv文件的目录下,本“变更文言.csv”如果改行没有需要更改的单元格则删除,如果有变更的单元格则只保留A到C内容以及变更单元格的内容(MAPPING 映射中的),def update_textid_csv(): """更新TEXTID.csv文件(先清空再写入模式) - 支持CR LF换行符""" if not os.path.exists(TEXTID_CSV): log(f"TEXTID.csv文件不存在: {TEXTID_CSV}") return if not csv_updates: log("没有需要更新的内容") return log("\n开始更新TEXTID.csv...") app_state.progress = 85 # 85%用于CSV更新 start_time = time.time() # 读取现有CSV内容 csv_rows = [] try: with open(TEXTID_CSV, 'r', encoding='utf-8-sig', newline='') as csvfile: reader = csv.reader(csvfile) csv_rows = list(reader) log(f"成功读取TEXTID.csv: 包含 {len(csv_rows)} 行") except Exception as e: error_msg = f"读取TEXTID.csv失败: {str(e)}\n{traceback.format_exc()}" log(error_msg) return # 精确统计更新次数 successful_update_count = 0 out_of_range_count = 0 total_updates = sum(len(v) for v in csv_updates.values()) # 计算进度步长 progress_step = max(1, 10 // max(1, total_updates)) current_progress = app_state.progress # 处理所有更新项 for row_idx, col_updates in csv_updates.items(): for col_idx, value in col_updates.items(): if col_idx == 1: # 跳过TXTID continue # 更新进度条 current_progress += progress_step app_state.progress = min(95, current_progress) # 标准化换行符为CR LF if isinstance(value, str): value = ( value .replace('\r\n', '\n') # 将CRLF统一转换为LF .replace('\r', '\n') # 将单独CR转换为LF .replace('\n', '\r\n') # 将所有LF转换为CRLF ) # 检查行是否存在 if row_idx < len(csv_rows): row_data = csv_rows[row_idx] # 扩展行长度(如果需要) if len(row_data) <= col_idx: row_data.extend([''] * (col_idx - len(row_data) + 1)) # 获取原始值用于日志记录 original_value = row_data[col_idx] if col_idx < len(row_data) else "" update_info = f"行{row_idx + 1}{chr(65 + col_idx)}: '{original_value}' → '{value}'" # 更新单元格值 row_data[col_idx] = value successful_update_count += 1 app_state.stats['csv_rows_updated'] += 1 # 记录成功的更新 log(f" ✓ 更新成功: {update_info}") else: # 行索引超出范围 out_of_range_count += 1 log(f" ⚠ 尝试更新行{row_idx + 1}{chr(65 + col_idx)}失败(超出CSV范围)") # 写回文件(支持CR LF换行) if successful_update_count > 0: try: # 备份原文件 backup_file = TEXTID_CSV + ".bak" shutil.copy2(TEXTID_CSV, backup_file) log(f"\n已创建备份: {backup_file}") # 写入更新内容(使用CR LF换行格式) with open(TEXTID_CSV, 'w', encoding='utf-8-sig', newline='') as csvfile: writer = csv.writer(csvfile) writer.writerows(csv_rows) log(f"TEXTID.csv更新完成: {TEXTID_CSV}") log(f" 成功更新: {successful_update_count} 个单元格") except Exception as e: error_msg = f"写入TEXTID.csv失败: {str(e)}\n{traceback.format_exc()}" log(error_msg) else: log("\n无有效更新内容") if out_of_range_count > 0: log(f" 警告: {out_of_range_count} 个更新尝试超出文件范围") elapsed_time = time.time() - start_time log(f"CSV更新耗时: {elapsed_time:.2f}秒") app_state.progress = 90 # 设置进度为90%以便进入下一步
最新发布
01-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值