基于正则匹配构建Crystal报表与库表字段关联的DataFrame
解决报表SQL中表与字段的关联匹配问题
核心思路
- 提前将数据库的表-字段关系整理为字典,避免重复遍历数据
- 对每个报表SQL,先定位所有用到的表,再针对每个表匹配其下属字段,确保字段与所属表绑定
- 使用正则边界匹配避免误匹配(如表名
Order不会匹配到OrderDetail)
改进后的代码
import pandas as pd import re # 1. 将数据库表-字段映射整理为字典(从cf DataFrame转换) table_columns = {} for _, row in cf.iterrows(): table = row['TABLE_NAME'] col = row['COLUMN_NAME'] if table not in table_columns: table_columns[table] = [] table_columns[table].append(col) # 2. 初始化结果列表,存储报表-表-字段关联数据 result_data = [] # 3. 遍历每个报表的SQL语句 for _, row in qf.iterrows(): sql = row['SQL'] report_name = row['FilenameCrystalReport'] # 清洗报表名称 cleaned_report = report_name.strip().replace("\\N", "N").replace("\\C", "C") if report_name else "Unknown Report" # 4. 找出当前SQL中用到的所有表 used_tables = [] for table in table_columns.keys(): # 正则完整匹配表名,转义特殊字符避免正则语法错误 pattern = re.compile(r'\b' + re.escape(table) + r'\b', re.IGNORECASE) if pattern.search(sql): used_tables.append(table) # 5. 对每个用到的表,匹配对应的字段(兼容带表前缀的字段写法) for table in used_tables: for col in table_columns[table]: col_pattern = re.compile( r'\b(?:{}\.)?{}\b'.format(re.escape(table), re.escape(col)), re.IGNORECASE ) if col_pattern.search(sql): result_data.append({ 'FilenameCrystalReport': cleaned_report, 'TableName': table, 'ColumnName': col }) # 6. 转换为符合要求的DataFrame并输出 result_df = pd.DataFrame(result_data) print(result_df.to_csv(sep=',', index=False))
关键优化点
- 表-字段映射字典:把分散的表和字段数据整合为结构化字典,大幅提升匹配效率,同时天然建立表与字段的关联关系
- 精准正则匹配:用
\b确保表名/字段名是完整匹配,re.escape处理含特殊字符的表名/字段名(如下划线、点),避免匹配错误 - 兼容多场景字段写法:支持纯字段名和
表名.字段名两种匹配模式,覆盖SQL中常见的字段引用方式 - 结构化结果存储:用列表收集标准化的字典数据,最终转换为DataFrame,直接输出符合期望的格式
输出示例
运行后会生成与需求一致的结果:
FilenameCrystalReport_A,TableNameA,Column A FilenameCrystalReport_A,TableNameA,Column B FilenameCrystalReport_A,TableNameA,Column C FilenameCrystalReport_B,TableNameA,Column A FilenameCrystalReport_B,TableNameZ,Column A FilenameCrystalReport_B,TableNameD,Column A
内容的提问来源于stack exchange,提问作者Jeff Barnes
相关产品推荐
相关产品推荐

