模板与数据源为什么要分开
报表出问题多半出在职责混装:模板里写了过滤条件与计算逻辑,结果同一个指标在月报、周报、大屏里各算一遍,数字对不上,改口径要改很多处。正确做法是分层——明细层存原始取数结果,汇总层做指标计算,报表视图层给出模板直接消费的字段,模板层只管版式与占位符。这样版式可以自由改,口径只在一处维护。
基本信息
| 模板层职责 | 版式、字段占位、单位与精度、分页与图表样式 |
|---|---|
| 数据源层职责 | 口径计算、维度与过滤、空值策略、数据边界 |
| 分层结构 | 明细层、汇总层、报表视图层、模板层 |
| 字段契约 | 字段名、类型、单位、空值语义、版本号 |
| 复用方式 | 同一结果集供多种版式与多语言模板消费 |
典型使用场景
- 同一指标多种版式:对外 PDF、内部表格、大屏用同一结果集
- 同一口径多种粒度:月度与季度报表共用汇总层,只换时间维度
- 多租户同模板:模板不变,按租户替换数据范围生成各自版本
- 口径调整:只改汇总层,所有消费方自动对齐
- 补数重跑:数据源补数后只重跑受影响层,模板与投递无需变动
分层职责与变更影响
| 层次 | 存放内容 | 变更影响范围 |
|---|---|---|
| 明细层 | 按周期与范围抽取的原始结果 | 补数只需重跑本层 |
| 汇总层 | 按维度聚合后的指标 | 口径变更集中在此层生效 |
| 报表视图 | 模板直接消费的字段集合 | 契约稳定,版式可自由调整 |
| 模板 | 版式、占位符、图表配置 | 只影响呈现,不改数字 |
| 分发配置 | 订阅关系与渠道参数 | 与数字无关,可独立调整 |
视图与模板的分工
视图与模板的分工
-- 汇总层:口径只写在这里,其他消费方统一引用
CREATE VIEW v_usage_monthly AS
SELECT tenant_id, resource_type,
SUM(usage_hours) AS usage_hours, -- 单位固定为小时
SUM(cost_amount) AS cost_amount -- 单位固定为元,精度到分
FROM fact_resource_usage
WHERE period = :period -- 时间边界在视图内定义
AND is_test = false -- 排除测试资源,避免口径分叉
GROUP BY tenant_id, resource_type;
-- 模板层只做取值与格式化:{{ usage_hours | round(2) }} 小时字段契约要带版本:模板只按契约取值,字段含义或单位变化必须升版本并通知消费方,否则版式还能跑但数字含义已经变了。
模板里写死过滤条件(租户、时间、环境)是最危险的复用方式:换一个租户生成报表时容易串数据,把其他租户的明细投递给无关人员。