跳转至

03 · 报表血缘逆向方法

谁需要这份:第 1 周做"现有系统数据源分析"的人。 背景前提:一期项目的开发文档大概率不全,必须对着数据库 + 报表反推难度:本指南最硬核的一篇,请耐心。


一、什么是"报表血缘"?为什么要做?

报表血缘(Data Lineage of Reports)= 报表上的每个字段,追溯到最原始的业务单据字段的完整路径。

一张图说明

[报表] 营收汇总表 · "已确认营收" 字段
   按合同号汇总
[中间表] t_revenue_confirm · confirmed_amount
   触发器:验收单审批通过时插入
[业务单据] t_acceptance · accepted_amount
   人工填写
[源头] 客户验收会签纸质文件

这条链路上任何一个环节有问题(手工拍数、计算错误、跳层填写),整张报表就是"假"的

为什么必须做?

  • 二期要重构数据模型,但你不能在不知道现状的情况下重构
  • 找出"假数据源"——一期最大的坑都在这里
  • 给开发的需求文档要写清楚"新数据从哪来",前提是搞清"旧数据从哪来"

工作量预估

  • 核心报表 20 张
  • 每张报表 10-30 个字段
  • 一个有经验的人,一个字段平均 15 分钟
  • 总计 50-80 工时,差不多就是第 1 周的全部精力

二、需要的输入材料

进场前向甲方索要:

材料 必要性 替代方案
现有系统数据库只读账号 ⭐必须 没有就直接告诉项目经理 W1 延期
现有报表的完整列表 + 最近一年实际数据 ⭐必须 至少要 5 张样本
数据库的 ER 图 / 数据字典 强烈推荐 用工具自动生成(见下文)
一期需求规格说明书、设计文档 推荐 没有就只能靠逆推
关键报表的 SQL 源码(如果是从数据库直出的) 推荐 没有就要靠访谈 IT
报表平台 / BI 工具的访问权限 推荐

⚠️ 没拿到只读账号前,不要开始 W1 Day 2-3 的工作。强行靠访谈推数据源会推到第 3 周还没头绪。


三、步骤 1:摸清数据库基础结构(Day 2 上午)

3.1 导出表清单

如果是 Oracle:

SELECT owner, table_name, num_rows, last_analyzed
FROM all_tables
WHERE owner NOT IN ('SYS', 'SYSTEM', 'XDB', 'OUTLN')
ORDER BY num_rows DESC;

如果是 PostgreSQL:

SELECT schemaname, tablename, n_live_tup as row_count
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;

如果是 SQL Server:

SELECT s.name AS schema_name, t.name AS table_name, p.rows
FROM sys.tables t
JOIN sys.schemas s ON t.schema_id = s.schema_id
JOIN sys.partitions p ON t.object_id = p.object_id
WHERE p.index_id IN (0,1)
ORDER BY p.rows DESC;

看表的判断技巧: - 行数 > 10 万的表,大概率是核心业务表 - 行数 < 100 的表,大概率是配置/字典表 - 表名含 loghistoryaudit 的是日志表 - 表名含 tmpbakold_xxxxxx_2023 的是历史残留 —— 这些往往是数据混乱的源头

3.2 导出字段清单

-- Oracle
SELECT table_name, column_name, data_type, data_length, nullable, data_default
FROM all_tab_columns
WHERE owner = 'YOUR_SCHEMA'
ORDER BY table_name, column_id;

-- PostgreSQL
SELECT table_name, column_name, data_type, character_maximum_length, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'public'
ORDER BY table_name, ordinal_position;

导出到 Excel,作为后续分析的基础表。

3.3 导出外键关系(找出实体关系网络)

-- PostgreSQL
SELECT
  tc.table_name AS from_table,
  kcu.column_name AS from_column,
  ccu.table_name AS to_table,
  ccu.column_name AS to_column
FROM information_schema.table_constraints tc
JOIN information_schema.key_column_usage kcu USING (constraint_name)
JOIN information_schema.constraint_column_usage ccu USING (constraint_name)
WHERE tc.constraint_type = 'FOREIGN KEY';

如果外键基本没有(一期开发偷懒,所有外键都是"逻辑外键"),这个事本身就是发现:

现有系统数据完整性靠应用层维护,存在数据不一致风险。

3.4 自动生成 ER 图

工具推荐(按优先级):

工具 优势 安装
DBeaver 免费、跨数据库、自动 ER 图 apt install dbeaver-ce
DataGrip JetBrains 出品,付费但好用
schemaspy 命令行生成完整 HTML 站点 docker 一行启动
pgAdmin 仅 PostgreSQL,免费

schemaspy 例子(你给数据库连接,它给你一个完整 HTML 网站):

docker run -v "$PWD/output:/output" --rm schemaspy/schemaspy:latest \
  -t pgsql11 -host 10.0.0.1 -port 5432 -db your_db \
  -u readonly_user -p password -o /output

第 1 周结束前,目标是手里有一份: - 全表清单 Excel(含行数、估计的业务用途) - ER 图(哪怕只覆盖核心 30 张表)


四、步骤 2:找出"核心 20 张报表"(Day 2 下午)

不要试图分析所有报表,20% 的报表覆盖 80% 的决策

4.1 怎么定"核心"

按下面三个维度打分(1-5 分):

维度 说明
使用频率 谁多久看一次?
决策权重 是否进入管理层例会?
数据复杂度 涉及多少业务模块?

总分 ≥ 10 分的,进入"核心 20 张"。

4.2 模板:核心报表清单

序号 报表名称 主用户 频率 决策用途 字段数 优先级
1 营收汇总表 财务总监 集团报表 25 P0
2 项目利润分析表 副总 经营分析会 32 P0
3 应收账龄分析 资金主管 催收决策 18 P0
4 ... ... ... ... ... ...

4.3 拿到样本数据

要至少 3 个月的实际报表(不要拿测试数据 / 演示数据),这是后面找异常的基础。


五、步骤 3:单张报表的血缘分析(Day 3)

这是真正的硬活。对每张核心报表执行下面的 5 步

5.1 第一步:找到报表的 SQL 源

三种可能: 1. 从 BI 平台导出:FineReport / 帆软 / 永洪 / Tableau / Power BI 自带血缘 2. 从应用代码里找:找 report_xxx.sql 这种文件 3. 数据库里 Profile:在生成报表的时段开启慢查询日志或 SQL 跟踪

如果以上都不行,直接问 IT:"这个报表的取数 SQL 给我看一下"。

5.2 第二步:拆解 SQL,建立字段映射

把 SQL 拆成 SELECT 部分 vs FROM/JOIN 部分

示例 SQL:

SELECT
  c.contract_no,
  c.contract_name,
  c.total_amount,                                    -- 字段1
  COALESCE(r.confirmed_revenue, 0) AS revenue,       -- 字段2
  c.total_amount - COALESCE(r.confirmed_revenue,0)
    AS remaining_revenue                             -- 字段3
FROM t_contract c
LEFT JOIN (
  SELECT contract_id, SUM(amount) AS confirmed_revenue
  FROM t_revenue_confirm
  WHERE status = 'CONFIRMED'
  GROUP BY contract_id
) r ON r.contract_id = c.id
WHERE c.status NOT IN ('DRAFT', 'CANCELLED');

对应映射表:

报表字段 来源表 来源字段 计算逻辑 过滤条件
合同号 t_contract contract_no 直接
合同金额 t_contract total_amount 直接
已确认收入 t_revenue_confirm amount SUM 聚合 status='CONFIRMED'
剩余收入 计算字段 合同金额 - 已确认收入 派生

5.3 第三步:追溯每个字段的"上一层来源"

刚才表层映射只到字段。但 t_revenue_confirm.amount 是怎么进来的?

继续追: - 这个表的插入触发是什么?(应用代码?触发器?人工导入?) - 插入时的取数来源是什么?

可能的答案: - 应用代码:用户在"收入确认"页面填入 → 来源是人工 - 触发器:当 t_acceptance.status 更新为已审批 → 来源是验收单 - ETL:每月从财务系统导入 → 来源是外部系统

追到"原始事件"为止:人工输入 / 外部接口 / 计算派生。

5.4 第四步:判断数据质量

每个原始来源做下面的检查:

来源类型 检查项
人工输入 有没有校验规则?谁负责?历史出错率?
外部接口 接口频率?延迟?失败如何处理?最近一次成功时间?
计算派生 公式是否一致?多处计算结果是否相同?
触发器/存储过程 是否还在运行?最近一次执行?

5.5 第五步:标记"假数据源"

满足下面任一条件,该字段标记为"假数据源": - ⚠️ 字段来源追不到(数据库里有数但没人知道哪来的) - ⚠️ 数据由人工每月覆盖式填入,没有过程数据 - ⚠️ 多个数据源都指向这个字段,但规则不一致 - ⚠️ 字段值与上游业务单据的对应字段经常不一致(抽样验证) - ⚠️ 字段值与同期其他报表的同名字段对不上

5.6 单张报表的产出模板

# 报表血缘分析 · [报表名]

## 基本信息
- 报表ID/名称:
- 主用户:
- 使用频率:
- 数据范围:
- 性能:单次生成耗时 X 秒
- 取数 SQL:附件 / 参考代码位置

## 字段血缘表

| 报表字段 | 来源表.字段 | 计算逻辑 | 原始事件 | 数据质量 | 标记 |
|---|---|---|---|---|---|
|  |  |  |  |  | 真/假/疑 |

## 数据质量问题汇总
1. 假数据源:[字段列表]
2. 数据不一致:[字段 vs 字段]
3. 性能问题:[哪些计算特别慢]
4. 业务规则不明:[规则说不清的字段]

## 重构建议
(W3 工作坊讨论后回填)

六、步骤 4:横向汇总(Day 3 末 - Day 4 早)

把 20 张报表的分析结果横向对比,找出全局问题

6.1 同一指标多版本

举例: - "已确认营收" 在三张报表都有,但数值不一样 - 报表 A:t_revenue_confirm.amount(财务口径) - 报表 B:t_project_revenue.amount(项目管理口径,手工填) - 报表 C:t_legacy_old.income(一期遗留,已无人维护) - 结论:同一指标 3 个源头,二期必须收敛

这种发现写进"现有系统数据源分析报告"的"全局问题"章节。

6.2 "孤儿字段" 与 "孤儿表"

  • 孤儿字段:数据库里有,但所有报表都没用
  • 可能是历史遗留,可以下线
  • 也可能是应该用但没人用(说明业务流程没走到)
  • 孤儿表:整张表所有报表都没用
  • 找 IT 确认能不能下线

6.3 数据流"断点"

某个业务事件本应触发数据流转,但实际没有。如: - 合同变更应该联动计划,但实际计划要手工改 - 验收单审批应该自动生成收入确认,但实际人工触发

这些"断点"就是二期的自动化机会点


七、产出物:现有系统数据源分析报告(W1 末完成)

最终文档结构:

1. 摘要
   - 分析覆盖范围(报表数 / 字段数 / 表数)
   - 关键发现 Top 5
   - 重构建议总览

2. 数据库总体情况
   - 表数 / 字段数 / 关系完整度
   - 主要业务实体 ER 图
   - 系统模块划分

3. 核心 20 张报表的血缘分析(每张报表 1 节)

4. 全局数据质量问题
   - 假数据源清单
   - 同一指标多版本问题
   - 数据流断点
   - 孤儿表/字段
   - 性能问题点

5. 二期重构建议(初步)
   - 必须重构(P0)
   - 应该重构(P1)
   - 可以保留(P2)

6. 附录
   - 全表清单
   - 全字段清单
   - 关键 SQL 摘录

这份文档是 W1 的核心产出,决定了 W2 访谈的精度


八、避坑提示

8.1 不要陷入"分析所有表"的执念

数据库里 500 张表,每张都分析你会做到地老天荒。只关心被报表用到的、被业务用到的

8.2 不要在 SQL 里花太多时间

你的目标是搞清"业务逻辑",不是优化 SQL。SQL 看懂就行。

8.3 不要绕过 IT 直接查数据库

哪怕你有只读账号,做任何分析前先在 IT 群里告知"我现在要跑分析 SQL"。生产数据库性能事故是项目最大风险之一。

8.4 不要相信"老文档"

一期的设计文档大概率和实际数据库对不上以数据库为准,文档作为参考

8.5 留好痕迹

每分析一张表/报表,把 SQL、查询结果、判断依据全部存档。后面 W3 工作坊有人质疑你的分析时,要能马上拿出来。


下一步 → 04 · 跟岗观察手册