159 lines
5.3 KiB
Markdown
159 lines
5.3 KiB
Markdown
---
|
|
name: requirements-analysis
|
|
description: 当用户提出统计、取数、报表、指标、转化率、漏斗、留存、活跃、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 完整日”,统一解释为左闭右开窗口:
|
|
|
|
```text
|
|
[start, end) = [current_date() - N days, current_date())
|
|
```
|
|
|
|
Spark/Hive SQL 应表达为:
|
|
|
|
```sql
|
|
event_time >= date_sub(current_date(), N)
|
|
AND event_time < current_date()
|
|
```
|
|
|
|
不要使用下面写法表示 timestamp 完整日窗口:
|
|
|
|
```sql
|
|
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 摘要。
|
|
|
|
```markdown
|
|
## 需求说明
|
|
|
|
### 业务目标
|
|
...
|
|
|
|
### 统计口径
|
|
- 统计对象:...
|
|
- 时间范围:近 N 天 T-1 完整日,`event_time >= date_sub(current_date(), N)` 且 `event_time < current_date()`
|
|
- 维度:...
|
|
- 指标:...
|
|
|
|
### 涉及表
|
|
| 表名 | 用途 | 粒度 | 使用字段 |
|
|
|---|---|---|---|
|
|
|
|
### 表关系
|
|
| 左表字段 | 右表字段 | Join 类型 | 风险 |
|
|
|---|---|---|---|
|
|
|
|
### 字段清单
|
|
| 表名 | 字段 | 用途 | 角色 |
|
|
|---|---|---|---|
|
|
|
|
### 实现逻辑
|
|
1. ...
|
|
|
|
### 待确认问题
|
|
无,或列出阻塞问题。
|
|
```
|
|
|
|
## 结构化输出
|
|
|
|
```yaml
|
|
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。
|