技术

SQL 写对了,答案为什么还会错?

查询成功不等于业务答案可信。本文拆解语义、粒度、时间、状态和版本五类错误,并给出从指标契约到证据交付的校验链。

技术 #Data Agent#NL2SQL#语义层#指标治理#数据质量#Text-to-SQL

数据分析里最危险的结果,往往不是一条报错的 SQL,而是一条顺利运行、数字精确、图表漂亮,却回答了错误问题的 SQL。

假设运营问:“本月新增客户是多少?”系统找到 customer 表,按 created_at 统计去重 ID,返回 12,486。查询没有语法错误,结果也能复现。但销售团队口中的“新增客户”是首次付费客户,财务还要求排除退款和内部测试账户。12,486 只是“本月新建客户记录”,不是提问者准备据此做预算的指标。

SQL 没有错。错误发生在 SQL 之前。

正确性不是一个开关,而是一条链

一项数据结论至少要通过四层正确性:

  1. 语法正确:查询能被数据库解析和执行。
  2. 数据正确:表、Join、粒度、时间和质量状态符合任务要求。
  3. 口径正确:计算使用了组织认可、在当前时间有效的业务定义。
  4. 解释正确:结论没有超出证据,限制条件和不确定性被如实表达。

大多数 Text-to-SQL 指标首先测的是前两层的一部分。企业真正承担决策风险的,却是后两层。

可信数据答案的五段校验链

五种常见的“正确地算错”

1. 同一个词,在不同团队代表不同事件

“客户”可能是注册用户、通过认证的企业、首次付费账户或签署合同的主体。“收入”可能是下单金额、支付金额、确认收入或扣除退款后的净收入。字段名相似,并不能证明业务含义相同。

Agent 如果静默选择一个定义,会让偶然的猜测看起来像确定事实。更好的行为是检索权威定义;存在多个有效口径时,把候选项和数字影响展示给用户确认。

2. 时间窗口没有对齐

“本月”可能指自然月、最近 30 天、财务账期,也可能受用户时区影响。同比还隐含工作日、节假日和完整周期是否可比。SQL 中一个看似无害的 CURRENT_DATE - 30,就可能改变管理层对趋势的判断。

3. Join 改变了数据粒度

订单表是一行一单,商品明细是一行一个 SKU。两表直接 Join 后对订单金额求和,会把多商品订单重复计算。查询能运行,抽样看起来也合理,只有先声明目标粒度并检查 Join 前后的行数和唯一键,才容易发现问题。

4. 状态过滤散落在历史 SQL 里

是否排除取消单、退款单、测试账户和风控交易,经常没有写在字段说明里,而是藏在某张看板或某位分析师维护的查询中。只给 Agent schema,相当于只给它词典,没有给它组织的会计规则。

5. 定义已经改变,答案仍在引用旧版本

指标口径会随业务发展而调整。文档、看板、语义层和历史 SQL 如果不同步,同一问题在不同入口会出现多个“官方答案”。这类版本漂移必须通过负责人、生效时间和弃用状态处理,不能靠模型选择看起来最新的一段文字。

为什么把更多 schema 塞进上下文仍不够

Spider 2.0 把 Text-to-SQL 放进更接近企业的环境:632 个工作流问题,数据库经常包含上千列,任务还需要检索元数据、方言文档和项目代码。论文发布时的基线结果显示,经典基准上的高分并不会直接迁移到这种复杂环境。

2026 年的 EntSQL 又把问题推进了一步:即使表结构已知,查询仍可能依赖内部指标、报告惯例和组织规则。它说明企业知识不是 schema 的注释版;还需要解决检索优先级、版本、生效范围和冲突。

同年 ICLR 收录的 BIRD-INTERACT 进一步把澄清、知识检索和执行错误恢复放回评测环境。现实任务不是一次性猜中标准 SQL,而是在互动中逐步消除不确定性。

把口径变成可执行的指标契约

一段业务描述要进入生产系统,最好先变成机器可读、可版本化的指标契约。核心字段至少包括:

契约字段需要回答的问题
名称与业务定义这个指标描述什么,不描述什么?
公式与组成项分子、分母、去重键和派生逻辑是什么?
实体与粒度每一行或每一个结果代表谁、何时、什么层级?
默认过滤取消、退款、测试和异常状态如何处理?
时间语义事件时间、入库时间、时区和完整性规则是什么?
版本与生效期哪个版本适用于当前查询,旧版本何时停止使用?
负责人发生冲突时由谁裁决?

语义层的作用,不只是把友好名称映射到字段,而是把这份契约编译成稳定的查询接口。Agent 应调用契约,而不是每次重新发明指标。

一条适合 Data Agent 的校验流程

查询前:先固定问题和口径

  • 识别业务对象、时间范围、决策用途和需要的比较基线。
  • 从认证的语义层或指标目录取得定义,并记录版本。
  • 如果存在多个合法解释,先澄清;不要用模型置信度替代业务确认。

查询中:守住粒度和数据质量

  • 为每个中间结果声明主键和目标粒度。
  • 检查 Join 前后的行数、唯一键和重复率。
  • 验证数据新鲜度、分区完整性、空值和异常波动。
  • 使用调用者身份执行,让权限系统而不是提示词决定可见数据。

查询后:验证结论而不只看结果集

  • 与已认证报表或已验证查询做数量级和趋势对照。
  • 对比替代口径,判断结论是否对定义敏感。
  • 保存 SQL、参数、指标版本、数据时间和检查结果。
  • 无法排除冲突时停止高置信度输出,明确列出待确认项。

评测也要从 SQL 扩展到答案

单独统计执行准确率,会奖励“碰巧返回同样结果”的查询,也看不到澄清和治理能力。企业自建评测集至少应增加:

  • 指标定义命中率:是否选择了正确版本和适用范围。
  • 澄清质量:该问时能否问到影响答案的最小问题集。
  • 粒度与 Join 安全率:是否发现重复聚合和实体错配。
  • 跨问法一致率:同一业务概念换一种说法,计算逻辑是否稳定。
  • 证据完整率:答案能否回到 SQL、数据源、指标版本和质量检查。
  • 漂移发现时延:口径更新后,旧答案多久会被阻断或标记。

真正可信的 Data Agent,不是永远给出一个数字,而是知道一个数字在什么条件下才有资格成为答案。