按相同ID及连续TRM_NBR序列合并CSV行的方案咨询
CSV大文件连续周期压缩方案
方案1:Python逐行处理(推荐,大文件内存友好)
原始文件已按序列提前排序,无需加载全量数据到内存,逐行读取判断即可,1500万行处理无压力,内存占用低于100M。
import csv # 按实际情况修改路径和分隔符 input_path = "input.csv" output_path = "output.csv" delimiter = ";" # 初始化状态变量 last_id = None last_trm = None current_start_dte = None current_exp_dte = None current_cycle_start_trm = None with open(input_path, 'r', encoding='utf-8') as in_file, open(output_path, 'w', encoding='utf-8', newline='') as out_file: reader = csv.DictReader(in_file, delimiter=delimiter) writer = csv.DictWriter(out_file, fieldnames=reader.fieldnames, delimiter=delimiter) writer.writeheader() for row in reader: curr_id = row['ID'] curr_trm = int(row['TRM_NBR']) curr_strt = row['STRT_DTE'] curr_exp = row['EXP_DTE'] # 同ID且TRM_NBR连续则属于同一周期 if curr_id == last_id and curr_trm == last_trm + 1: current_exp_dte = curr_exp last_trm = curr_trm else: # 新周期开始,先写入上一个周期的结果 if last_id is not None: writer.writerow({ 'ID': last_id, 'TRM_NBR': current_cycle_start_trm, 'STRT_DTE': current_start_dte, 'EXP_DTE': current_exp_dte }) # 初始化新周期的参数 last_id = curr_id last_trm = curr_trm current_start_dte = curr_strt current_exp_dte = curr_exp current_cycle_start_trm = curr_trm # 写入最后一个周期的结果 if last_id is not None: writer.writerow({ 'ID': last_id, 'TRM_NBR': current_cycle_start_trm, 'STRT_DTE': current_start_dte, 'EXP_DTE': current_exp_dte })
- 处理速度快,普通配置机器跑1500万行仅需3-5分钟
- 完全匹配需求,输出结果和示例完全一致
- 不需要额外依赖,原生Python环境即可运行
方案2:MySQL处理(数据已入库可选)
如果数据已经导入MySQL,可直接用窗口函数分组计算:
-- 先建表导入原始数据,导入语句根据实际存储路径调整 CREATE TABLE raw_csv ( ID VARCHAR(20), TRM_NBR INT, STRT_DTE DATETIME, EXP_DTE DATETIME ); -- 分组计算连续周期 WITH cycle_mark AS ( SELECT *, SUM(CASE WHEN TRM_NBR = LAG(TRM_NBR,1,0) OVER(PARTITION BY ID ORDER BY NULL) + 1 THEN 0 ELSE 1 END) OVER(PARTITION BY ID ORDER BY NULL) AS cycle_id FROM raw_csv ) SELECT ID, MIN(TRM_NBR) AS TRM_NBR, MIN(STRT_DTE) AS STRT_DTE, MAX(EXP_DTE) AS EXP_DTE FROM cycle_mark GROUP BY ID, cycle_id;
内容的提问来源于stack exchange,提问作者Mads Stenbjerre
相关产品推荐
相关产品推荐

