Files
opencode-build/skills/requirements-analysis/SKILL.md
T
2026-07-01 17:46:08 +08:00

5.3 KiB

name, description
name description
requirements-analysis 当用户提出统计、取数、报表、指标、转化率、漏斗、留存、活跃、GMV、同环比、SQL/Hive/Spark/PySpark 数据开发需求时使用。先把模糊业务问题澄清成可交付的数据需求规格说明书 DRD,不直接写 SQL,不调用 MCP,不提交作业。

Requirements Analysis(需求澄清)

目标

把一句可能含糊的数据需求整理成正式 DRD。重点不是快点写 SQL,而是先把统计对象、时间窗口、指标分子分母、维度、表字段、join 和输出要求固定下来,避免“SQL 看起来对但数字口径错”。

本 skill 的输出是 requirements_output,下游只能基于它推进,不得重新解释业务口径。

工作顺序

  1. 复述业务目标:这个统计用于评估什么,最终交付什么。
  2. 定义输出粒度:结果一行代表什么维度组合。
  3. 明确统计对象:用户、订单、交易、设备、账户等。
  4. 明确时间口径:自然日、T-1 完整日、滚动窗口、时区、事件时间字段。
  5. 明确指标口径:分子、分母、去重键、过滤条件、空值策略。
  6. 明确维度口径:渠道、城市、产品、日期等分组字段来自哪张表。
  7. 明确数据来源:候选表、候选字段、字段含义、状态枚举、金额单位。
  8. 明确关联关系:主表、维表、join key、join 类型、1:N 风险。
  9. 明确结果要求:输出列、排序、是否落表、是否允许 overwrite。
  10. 如果任一关键口径不明确,停止并提问;如果已明确,输出 DRD 和 requirements_output

必问歧义

  • “近 30 天”是自然日、T-1 完整日,还是滚动到当前时刻。
  • “新用户”是首次注册、首次登录、首次下单、首次激活还是首次付费。
  • “成功”对应哪些状态码,退款、撤销、部分成功是否计入。
  • “转化率”的分子、分母、事件顺序、去重键和转化窗口是什么。
  • 分组维度来自事实表还是维表;维表缺失时是否保留 NULL。
  • 多表 join 后是否会产生重复行,是否要先去重或聚合。
  • 输出是临时查询还是要写入目标表。

时间口径硬规则

对“近 N 天按 T-1 完整日”,统一解释为左闭右开窗口:

[start, end) = [current_date() - N days, current_date())

Spark/Hive SQL 应表达为:

event_time >= date_sub(current_date(), N)
AND event_time < current_date()

不要使用下面写法表示 timestamp 完整日窗口:

event_time BETWEEN date_add(current_date(), -N) AND date_add(current_date(), -1)

因为它很容易只覆盖到结束日期的 00:00:00,漏掉 T-1 白天的数据。

转化口径硬规则

转化类需求必须写清:

  • 分母人群,例如“窗口内首次登录的新用户”。
  • 分子人群,例如“该新用户注册后存在成功付费”。
  • 事件顺序,例如 pay_time >= register_time
  • 后置事件是否也需要在统计窗口内。
  • 去重键,例如 user_id

如果用户说“注册后付费”,必须把“后”写进 DRD,不允许只写“注册且付费”。

正式 DRD 输出

当关键口径已明确时,必须先输出可读 DRD,再输出 YAML 摘要。

## 需求说明

### 业务目标
...

### 统计口径
- 统计对象:...
- 时间范围:近 N 天 T-1 完整日,`event_time >= date_sub(current_date(), N)``event_time < current_date()`
- 维度:...
- 指标:...

### 涉及表
| 表名 | 用途 | 粒度 | 使用字段 |
|---|---|---|---|

### 表关系
| 左表字段 | 右表字段 | Join 类型 | 风险 |
|---|---|---|---|

### 字段清单
| 表名 | 字段 | 用途 | 角色 |
|---|---|---|---|

### 实现逻辑
1. ...

### 待确认问题
无,或列出阻塞问题。

结构化输出

requirements_output:
  status: READY_FOR_METADATA | NEED_USER_CONFIRMATION
  business_goal: "一句话业务目标"
  grain: "结果一行代表什么"
  time_window:
    description: "时间窗口"
    timezone: "时区"
    event_time_hint: "候选时间字段"
    lower_bound_sql: "date_sub(current_date(), N)"
    upper_bound_sql: "current_date()"
    boundary: "left_closed_right_open"
  metrics:
    - name: "指标名"
      formula: "业务公式"
      numerator: "分子"
      denominator: "分母"
      dedupe_key: "去重键"
      order_constraint: "例如 pay_time >= register_time"
      null_policy: "空值处理"
  dimensions:
    - "分组维度"
  filters:
    - "过滤条件"
  candidate_tables:
    - business_role: "事实表/维表/码表/结果表"
      table_hint: "候选物理表"
  candidate_fields:
    - business_name: "业务字段名"
      role: dimension | metric | filter | time | join_key | output
      table_hint: "候选表"
      column_hint: "候选字段"
      required: true
  join_hints:
    - left: "表A.字段"
      right: "表B.字段"
      type_hint: left | inner | right | full | unknown
      cardinality_hint: "1:1 | 1:N | N:1 | N:N | unknown"
  output_columns:
    - "输出列"
  write_intent:
    mode: query_only | insert_into | insert_overwrite | unknown
    target_table: "可为空"
    overwrite_confirmed: false
  pending_questions: []

停止条件

只要 pending_questions 非空,就输出 NEED_USER_CONFIRMATION,不要进入元数据校验,更不要写 SQL。