数仓开发的三层责任:业务定义、模型设计与 SQL 实现

同一笔订单,为什么几张报表会给出不同的"销售额"?遇到这种情况,直接查 SQL 往往只能解决一部分问题。

一份数仓结果要可信,需要三层责任共同成立:业务定义说清要回答什么,模型设计保留必要事实,SQL 实现正确完成计算。它们可以由同一个人承担,但每一层都需要单独验证。

一、先看业务:同一笔订单,可以回答不同问题

假设一张订单包含两条商品明细,金额分别为60元和40元:

  • 3月31日创建订单。
  • 4月1日成功支付100元。
  • 4月3日成功退款20元。

以下为教学示例。为便于讨论,假设这张订单只有上述支付与退款,金额已完成核对。

如果经营者问"每天发生了多少支付和退款",应看到4月1日支付100元,4月3日退款20元。

如果问"4月1日支付的这批订单,后来保留了多少交易金额",截至4月3日,这张订单对应的净额是80元。

两个问题使用同一批记录,却采用不同的观察方式。前者看事件发生,后者追踪某批订单的后续结果。它们可以同时成立,关键是报表需要明确自己回答哪个问题。

业务定义,需要明确哪些条件

在这个例子里,至少要确认:

条件 需要说清的内容
用途 看每日活动,还是评价某批订单的后续表现?
事件与范围 统计下单、成功支付还是退款?包含哪些渠道和状态?
时间与归属 按哪个事件日期统计?退款归发生日还是原支付批次?
截止时点 数据截至什么时候?后续退款是否修正历史结果?
交付责任 谁确认定义,何时可用,口径变化由谁协调?

这就是第一层责任:把经营问题变成明确的分析约定。数据域负责人需要组织业务、源系统和开发共同确认,而不是让某个字段名称或程序默认行为替大家作决定。

如果两份报表用途不同,应分别命名并说明关系;如果声称回答同一个问题,就要对齐定义、范围和时间,再继续排查。

二、再看模型:数据能否正确表达这个问题

定义明确后,下一步是检查数据是否保留了足够的信息。

这笔业务至少包含三类记录:商品明细说明买了什么,支付记录说明何时付了多少,退款记录说明何时退了多少。它们的业务事件和粒度不同。

粒度,就是一行数据代表什么。

记录 示例粒度 主要说明什么
订单商品明细 一条订单商品行 商品、数量和行金额
支付记录 一笔支付业务记录 支付金额、状态和发生时间
退款记录 一笔退款业务记录 退款金额、状态和发生时间

如果只保留订单当前的"部分退款"状态,就可能无法还原每天发生了哪些退款。如果要把退款归回原支付批次,还需要可靠的关联关系,不能仅凭金额相同推测对应关系。

因此,模型设计要由问题逐步推导:先确定业务事件与粒度,再确定唯一身份、关联、时间及历史保留规则,最后考虑怎样汇总。

对于本例,按日观察支付和退款,需要保留各自的事件时间;追踪4月1日支付批次的后续净额,则要能够识别该批次关联的退款,并明确统计截止时点。

这就是第二层责任:让模型能够表达已经确认的业务含义。验证时既要检查正常交易,也要加入跨日、部分退款或多次退款等情况,确认历史仍然能够解释。

三、最后看 SQL:计算有没有改变业务含义

即使业务定义和模型都正确,SQL 仍可能把结果算错。

本例有两条商品明细和一条支付记录。如果按订单号直接连接,支付金额就可能被复制:

商品行金额 关联后的支付金额
60元 100元
40元 100元

此时再对支付金额求和,会得到200元。SQL可以正常执行,但一笔支付已经出现了两次。

问题在于连接两侧的粒度没有匹配好。若目标是计算每张订单截至某时点的支付后净额,可以分别将成功支付、成功退款按订单汇总,再在一行一订单的粒度上关联,得到本例的100-20=80元。

这个结果使用的是前面约定的订单批次口径,不应直接当作某一天的净交易额。如果需要进一步分析到商品,还必须确认支付、退款与商品行的关系或分摊规则。

也不能把 SUM(DISTINCT 支付金额) 当成通用补救。两笔真实支付可能恰好都是100元,按金额去重会把真实业务删掉。

怎样验证实现正确

SQL评审至少要检查四件事:

  1. 身份与粒度:一行代表什么,业务记录怎样唯一识别?
  2. 连接关系:关联前后,金额是否被复制,记录是否遗漏?
  3. 过滤规则:状态、时间、渠道是否符合约定?
  4. 对账与反例:明细能否对上汇总,跨日和多次退款是否仍成立?

这就是第三层责任:通过连接、过滤和聚合忠实落实业务定义,并用可复现的输入与预期结果证明它。

四、面对报表争议,按责任定位问题

把三层责任连起来,可以形成清楚的排查顺序:

先确认用途与口径,再检查模型表达,最后检查SQL计算,并完成对账和使用者验收。

责任 核心问题 验证依据
业务定义 究竟要回答什么? 用途、口径、时效和责任得到确认
模型设计 数据能否表达这个问题? 粒度、关联、时间与历史规则成立
SQL实现 计算是否落实了定义与模型? 反例、对账与验收通过

这条链也需要反馈。如果检查模型时发现源系统没有退款明细,就应回到需求层说明数据缺口,决定补充来源或调整分析范围。不能继续用SQL拼出一个缺乏证据的答案。

数仓开发者需要逐步具备贯通三层的能力:能够澄清定义、解释设计,并验证实现。当业务发生变化时,也能指出哪些模型、计算和下游结果需要随之调整。

阅读参考:《数据仓库工具箱:维度建模权威指南》第3版,第1章与第3章。作者官网与书籍介绍。文中的订单、金额与报表情境为本文构造的教学示例。

相关推荐
瀚高PG实验室1 小时前
瀚高数据库创建新数据库卡住问题排查
数据库·postgresql·瀚高数据库
瑶总迷弟1 小时前
银河麒麟 V10 ARM64 安装 Oracle 19c 静默部署操作手册
数据库·oracle
飞浪纪元[FWC–FE]2 小时前
Qt 工程创建与 CMake / qmake 构建规范
开发语言·数据库·qt
Ivanqhz2 小时前
MoE + LLM 应用
数据库·人工智能·pytorch·python·深度学习·算法·1024程序员节
Tsuki_tl2 小时前
【总结】Redis五大数据类型应用场景及基本命令
数据库·redis·后端·缓存·缓存中间件·redis命令·redis 五大数据类型
Gauss松鼠会2 小时前
GaussDB 整体架构解析
运维·服务器·网络·数据库·sql·架构·gaussdb
系统集成-鹰翔2 小时前
ERP对接升级提示数据库迁移失败:SQLite逐版本事务到底回滚到哪一步
javascript·数据库·经验分享·后端
西瓜拿铁好喝2 小时前
开源和闭源 AI 办公工具,分别适合谁
java·前端·数据库
代码派2 小时前
业务不停机迁移 MySQL 到 TiDB,NineData 数据增量同步实操演示
数据库·mysql·tidb·ninedata·无停机迁移·增量迁移·全量迁移