# 模板字段关联查询说明 ## 一、概述 本文档说明如何通过查询 `f_polic_file_config` 表获取每个模板关联的输入和输出字段。系统已重新建立了模板和字段的关联关系,不再依赖 `input_data` 和 `template_code` 字段。 ## 二、表结构关系 ### 2.1 相关表说明 1. **f_polic_file_config** - 文件模板配置表 - `id`: 文件配置ID(主键) - `name`: 模板名称(如:"初步核实审批表") - `tenant_id`: 租户ID(固定值:615873064429507639) - `state`: 状态(0=未启用,1=启用) 2. **f_polic_field** - 字段定义表 - `id`: 字段ID(主键) - `name`: 字段名称(中文显示名) - `filed_code`: 字段编码(注意:表中字段名拼写为 `filed_code`) - `field_type`: 字段类型(1=输入字段,2=输出字段) - `tenant_id`: 租户ID 3. **f_polic_file_field** - 文件和字段关联表 - `file_id`: 文件配置ID(关联 `f_polic_file_config.id`) - `filed_id`: 字段ID(关联 `f_polic_field.id`) - `tenant_id`: 租户ID - `state`: 状态(0=未启用,1=启用) ### 2.2 关联关系 ``` f_polic_file_config (模板) ↓ (通过 file_id) f_polic_file_field (关联表) ↓ (通过 filed_id) f_polic_field (字段) ``` ## 三、查询方式 ### 3.1 根据模板名称查询字段 **场景**:已知模板名称,查询该模板关联的所有字段(包括输入和输出字段) ```sql SELECT fc.id AS template_id, fc.name AS template_name, f.id AS field_id, f.name AS field_name, f.filed_code AS field_code, f.field_type, CASE WHEN f.field_type = 1 THEN '输入字段' WHEN f.field_type = 2 THEN '输出字段' ELSE '未知' END AS field_type_name FROM f_polic_file_config fc INNER JOIN f_polic_file_field fff ON fc.id = fff.file_id INNER JOIN f_polic_field f ON fff.filed_id = f.id WHERE fc.tenant_id = 615873064429507639 AND fc.name = '初步核实审批表' AND fc.state = 1 AND fff.state = 1 AND f.state = 1 ORDER BY f.field_type, f.name; ``` ### 3.2 根据模板ID查询字段 **场景**:已知模板ID,查询该模板关联的所有字段 ```sql SELECT f.id AS field_id, f.name AS field_name, f.filed_code AS field_code, f.field_type, CASE WHEN f.field_type = 1 THEN '输入字段' WHEN f.field_type = 2 THEN '输出字段' ELSE '未知' END AS field_type_name FROM f_polic_file_field fff INNER JOIN f_polic_field f ON fff.filed_id = f.id WHERE fff.file_id = ? -- 替换为实际的模板ID AND fff.tenant_id = 615873064429507639 AND fff.state = 1 AND f.state = 1 ORDER BY f.field_type, f.name; ``` ### 3.3 分别查询输入字段和输出字段 **场景**:需要分别获取输入字段和输出字段列表 #### 查询输入字段(field_type = 1) ```sql SELECT f.id AS field_id, f.name AS field_name, f.filed_code AS field_code FROM f_polic_file_config fc INNER JOIN f_polic_file_field fff ON fc.id = fff.file_id INNER JOIN f_polic_field f ON fff.filed_id = f.id WHERE fc.tenant_id = 615873064429507639 AND fc.name = '初步核实审批表' AND fc.state = 1 AND fff.state = 1 AND f.state = 1 AND f.field_type = 1 -- 输入字段 ORDER BY f.name; ``` #### 查询输出字段(field_type = 2) ```sql SELECT f.id AS field_id, f.name AS field_name, f.filed_code AS field_code FROM f_polic_file_config fc INNER JOIN f_polic_file_field fff ON fc.id = fff.file_id INNER JOIN f_polic_field f ON fff.filed_id = f.id WHERE fc.tenant_id = 615873064429507639 AND fc.name = '初步核实审批表' AND fc.state = 1 AND fff.state = 1 AND f.state = 1 AND f.field_type = 2 -- 输出字段 ORDER BY f.name; ``` ### 3.4 查询所有模板及其字段统计 **场景**:获取所有模板及其关联的字段数量统计 ```sql SELECT fc.id AS template_id, fc.name AS template_name, COUNT(DISTINCT CASE WHEN f.field_type = 1 THEN f.id END) AS input_field_count, COUNT(DISTINCT CASE WHEN f.field_type = 2 THEN f.id END) AS output_field_count, COUNT(DISTINCT f.id) AS total_field_count FROM f_polic_file_config fc LEFT JOIN f_polic_file_field fff ON fc.id = fff.file_id AND fff.state = 1 LEFT JOIN f_polic_field f ON fff.filed_id = f.id AND f.state = 1 WHERE fc.tenant_id = 615873064429507639 AND fc.state = 1 GROUP BY fc.id, fc.name ORDER BY fc.name; ``` ### 3.5 查询特定模板的完整字段信息(JSON格式) **场景**:前端需要获取模板的完整字段信息,包括输入和输出字段的详细信息 ```sql SELECT fc.id AS template_id, fc.name AS template_name, JSON_OBJECT( 'input_fields', JSON_ARRAYAGG( CASE WHEN f.field_type = 1 THEN JSON_OBJECT( 'id', f.id, 'name', f.name, 'field_code', f.filed_code ) END ), 'output_fields', JSON_ARRAYAGG( CASE WHEN f.field_type = 2 THEN JSON_OBJECT( 'id', f.id, 'name', f.name, 'field_code', f.filed_code ) END ) ) AS fields_info FROM f_polic_file_config fc LEFT JOIN f_polic_file_field fff ON fc.id = fff.file_id AND fff.state = 1 LEFT JOIN f_polic_field f ON fff.filed_id = f.id AND f.state = 1 WHERE fc.tenant_id = 615873064429507639 AND fc.name = '初步核实审批表' AND fc.state = 1 GROUP BY fc.id, fc.name; ``` ## 四、Python代码示例 ### 4.1 根据模板名称获取字段 ```python import pymysql # 数据库配置 DB_CONFIG = { 'host': '152.136.177.240', 'port': 5012, 'user': 'finyx', 'password': '6QsGK6MpePZDE57Z', 'database': 'finyx', 'charset': 'utf8mb4' } TENANT_ID = 615873064429507639 def get_template_fields_by_name(template_name: str): """ 根据模板名称获取关联的字段 Args: template_name: 模板名称,如 '初步核实审批表' Returns: dict: 包含 input_fields 和 output_fields 的字典 """ conn = pymysql.connect(**DB_CONFIG) cursor = conn.cursor(pymysql.cursors.DictCursor) try: sql = """ SELECT f.id, f.name, f.filed_code AS field_code, f.field_type FROM f_polic_file_config fc INNER JOIN f_polic_file_field fff ON fc.id = fff.file_id INNER JOIN f_polic_field f ON fff.filed_id = f.id WHERE fc.tenant_id = %s AND fc.name = %s AND fc.state = 1 AND fff.state = 1 AND f.state = 1 ORDER BY f.field_type, f.name """ cursor.execute(sql, (TENANT_ID, template_name)) fields = cursor.fetchall() # 分类为输入字段和输出字段 result = { 'template_name': template_name, 'input_fields': [], 'output_fields': [] } for field in fields: field_info = { 'id': field['id'], 'name': field['name'], 'field_code': field['field_code'], 'field_type': field['field_type'] } if field['field_type'] == 1: result['input_fields'].append(field_info) elif field['field_type'] == 2: result['output_fields'].append(field_info) return result finally: cursor.close() conn.close() # 使用示例 if __name__ == '__main__': result = get_template_fields_by_name('初步核实审批表') print(f"模板: {result['template_name']}") print(f"输入字段数量: {len(result['input_fields'])}") print(f"输出字段数量: {len(result['output_fields'])}") print("\n输入字段:") for field in result['input_fields']: print(f" - {field['name']} ({field['field_code']})") print("\n输出字段:") for field in result['output_fields']: print(f" - {field['name']} ({field['field_code']})") ``` ### 4.2 根据模板ID获取字段 ```python def get_template_fields_by_id(template_id: int): """ 根据模板ID获取关联的字段 Args: template_id: 模板ID Returns: dict: 包含 input_fields 和 output_fields 的字典 """ conn = pymysql.connect(**DB_CONFIG) cursor = conn.cursor(pymysql.cursors.DictCursor) try: # 先获取模板名称 sql_template = """ SELECT id, name FROM f_polic_file_config WHERE id = %s AND tenant_id = %s AND state = 1 """ cursor.execute(sql_template, (template_id, TENANT_ID)) template = cursor.fetchone() if not template: return None # 获取字段 sql_fields = """ SELECT f.id, f.name, f.filed_code AS field_code, f.field_type FROM f_polic_file_field fff INNER JOIN f_polic_field f ON fff.filed_id = f.id WHERE fff.file_id = %s AND fff.tenant_id = %s AND fff.state = 1 AND f.state = 1 ORDER BY f.field_type, f.name """ cursor.execute(sql_fields, (template_id, TENANT_ID)) fields = cursor.fetchall() result = { 'template_id': template['id'], 'template_name': template['name'], 'input_fields': [], 'output_fields': [] } for field in fields: field_info = { 'id': field['id'], 'name': field['name'], 'field_code': field['field_code'], 'field_type': field['field_type'] } if field['field_type'] == 1: result['input_fields'].append(field_info) elif field['field_type'] == 2: result['output_fields'].append(field_info) return result finally: cursor.close() conn.close() ``` ### 4.3 获取所有模板及其字段统计 ```python def get_all_templates_with_field_stats(): """ 获取所有模板及其字段统计信息 Returns: list: 模板列表,每个模板包含字段统计 """ conn = pymysql.connect(**DB_CONFIG) cursor = conn.cursor(pymysql.cursors.DictCursor) try: sql = """ SELECT fc.id AS template_id, fc.name AS template_name, COUNT(DISTINCT CASE WHEN f.field_type = 1 THEN f.id END) AS input_field_count, COUNT(DISTINCT CASE WHEN f.field_type = 2 THEN f.id END) AS output_field_count, COUNT(DISTINCT f.id) AS total_field_count FROM f_polic_file_config fc LEFT JOIN f_polic_file_field fff ON fc.id = fff.file_id AND fff.state = 1 LEFT JOIN f_polic_field f ON fff.filed_id = f.id AND f.state = 1 WHERE fc.tenant_id = %s AND fc.state = 1 GROUP BY fc.id, fc.name ORDER BY fc.name """ cursor.execute(sql, (TENANT_ID,)) templates = cursor.fetchall() return [ { 'template_id': t['template_id'], 'template_name': t['template_name'], 'input_field_count': t['input_field_count'] or 0, 'output_field_count': t['output_field_count'] or 0, 'total_field_count': t['total_field_count'] or 0 } for t in templates ] finally: cursor.close() conn.close() # 使用示例 if __name__ == '__main__': templates = get_all_templates_with_field_stats() print("所有模板及其字段统计:") for template in templates: print(f"\n模板: {template['template_name']} (ID: {template['template_id']})") print(f" 输入字段: {template['input_field_count']} 个") print(f" 输出字段: {template['output_field_count']} 个") print(f" 总字段数: {template['total_field_count']} 个") ``` ## 五、常见查询场景 ### 5.1 前端展示模板列表 **需求**:前端需要展示所有模板,并显示每个模板的字段数量 ```sql SELECT fc.id, fc.name, COUNT(DISTINCT CASE WHEN f.field_type = 1 THEN f.id END) AS input_count, COUNT(DISTINCT CASE WHEN f.field_type = 2 THEN f.id END) AS output_count FROM f_polic_file_config fc LEFT JOIN f_polic_file_field fff ON fc.id = fff.file_id AND fff.state = 1 LEFT JOIN f_polic_field f ON fff.filed_id = f.id AND f.state = 1 WHERE fc.tenant_id = 615873064429507639 AND fc.state = 1 GROUP BY fc.id, fc.name ORDER BY fc.name; ``` ### 5.2 验证模板字段完整性 **需求**:检查某个模板是否有关联字段 ```sql SELECT fc.id, fc.name, CASE WHEN COUNT(f.id) > 0 THEN '有字段关联' ELSE '无字段关联' END AS status, COUNT(f.id) AS field_count FROM f_polic_file_config fc LEFT JOIN f_polic_file_field fff ON fc.id = fff.file_id AND fff.state = 1 LEFT JOIN f_polic_field f ON fff.filed_id = f.id AND f.state = 1 WHERE fc.tenant_id = 615873064429507639 AND fc.name = '初步核实审批表' AND fc.state = 1 GROUP BY fc.id, fc.name; ``` ### 5.3 查找使用特定字段的所有模板 **需求**:查找哪些模板使用了某个字段(如 `target_name`) ```sql SELECT fc.id AS template_id, fc.name AS template_name FROM f_polic_file_config fc INNER JOIN f_polic_file_field fff ON fc.id = fff.file_id INNER JOIN f_polic_field f ON fff.filed_id = f.id WHERE fc.tenant_id = 615873064429507639 AND f.tenant_id = 615873064429507639 AND f.filed_code = 'target_name' AND fc.state = 1 AND fff.state = 1 AND f.state = 1 ORDER BY fc.name; ``` ## 六、注意事项 1. **租户ID**:所有查询都需要使用固定的租户ID:`615873064429507639` 2. **状态过滤**:建议始终过滤 `state = 1` 的记录,确保只获取启用的模板和字段 3. **字段名拼写**:注意 `f_polic_field` 表中的字段编码字段名是 `filed_code`(不是 `field_code`),这是历史遗留问题 4. **字段类型**: - `field_type = 1`:输入字段(用于AI解析的原始数据) - `field_type = 2`:输出字段(AI解析后生成的结构化数据,用于填充模板) 5. **关联表状态**:`f_polic_file_field` 表也有 `state` 字段,需要过滤 `fff.state = 1` 6. **性能优化**:如果经常查询,建议在以下字段上创建索引: - `f_polic_file_config.tenant_id` - `f_polic_file_config.name` - `f_polic_file_field.file_id` - `f_polic_file_field.filed_id` - `f_polic_field.filed_code` ## 七、示例数据 ### 7.1 初步核实审批表字段示例 **输入字段**(2个): - `clue_info` - 线索信息 - `target_basic_info_clue` - 被核查人员工作基本情况线索 **输出字段**(14个): - `target_name` - 被核查人姓名 - `target_organization_and_position` - 被核查人员单位及职务 - `target_organization` - 被核查人员单位 - `target_position` - 被核查人员职务 - `target_gender` - 被核查人员性别 - `target_date_of_birth` - 被核查人员出生年月 - `target_age` - 被核查人员年龄 - `target_education_level` - 被核查人员文化程度 - `target_political_status` - 被核查人员政治面貌 - `target_professional_rank` - 被核查人员职级 - `clue_source` - 线索来源 - `target_issue_description` - 主要问题线索 - `department_opinion` - 初步核实审批表承办部门意见 - `filler_name` - 初步核实审批表填表人 ## 八、总结 通过 `f_polic_file_field` 关联表,可以方便地查询每个模板关联的输入和输出字段。这种方式比之前依赖 `input_data` 和 `template_code` 字段更加规范、可靠,也更容易维护和扩展。 其他研发人员可以根据上述SQL示例和Python代码,在自己的模块中实现模板字段的查询功能。