531 lines
16 KiB
Markdown
531 lines
16 KiB
Markdown
# 模板字段关联查询说明
|
||
|
||
## 一、概述
|
||
|
||
本文档说明如何通过查询 `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代码,在自己的模块中实现模板字段的查询功能。
|
||
|