---
name: sql-review
description: 当一条 Spark SQL 已经生成、通过 guardrails 并准备展示或执行前使用。它基于 sql_context 静态检查字段引用、alias、join key、数据膨胀、重复聚合、时间过滤、转化顺序、GROUP BY、空值、类型和写入风险，只报告问题，不直接改 SQL。
---

# SQL Review（SQL 静态评审）

## 目标

在 SQL 执行前做质量检查，发现可能导致数字错误、执行失败或性能风险的问题。评审只报告风险和建议，不负责直接改写 SQL。

## 输入

```yaml
sql: "待评审的 Spark SQL"
sql_context:
  status: CONTEXT_READY
sql_guard:
  status: PASS
logic_plan:
  status: PLANNED
```

如果没有 `sql_context`，也可以继续做基础结构检查，但必须报告一个 HIGH 风险：缺少上下文，无法保证字段和 join 正确。

## 检查项

1. 字段引用：每个 `alias.column` 是否存在于 `sql_context.fields`。
2. alias：SQL 是否发明了 context 中没有的 alias。
3. join key：ON 条件是否匹配 context 中固定的 join。
4. join 基数：1:N 或 N:N join 是否会造成数据膨胀。
5. 指标公式：聚合表达式是否符合 logic plan 和 context。
6. 重复聚合：同一指标是否被重复 sum/count。
7. 时间过滤：事实表是否缺少必要时间或分区过滤。
8. 时间边界：T-1 完整日是否使用左闭右开窗口。
9. 转化顺序：后置事件是否满足前置事件之后发生。
10. GROUP BY：非聚合输出列是否都在 group by 中。
11. 空值策略：join key 和度量字段是否需要 coalesce 或保留策略。
12. 类型匹配：字符串日期、字符串金额是否需要 cast。
13. 写入风险：INSERT 目标列、overwrite 确认、分区覆盖范围是否明确。
14. 执行成本：是否存在无分区裁剪的大表全扫、笛卡尔积、窗口无 partition。

## 时间边界检查

当需求为“近 N 天按 T-1 完整日”且字段是 timestamp/date-like：

推荐：

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

风险写法：

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

如果 SQL 使用风险写法，至少标为 `MEDIUM`；如果会明显漏掉结束日期白天数据，标为 `HIGH`。

## 转化顺序检查

对注册、付费、激活、下单等漏斗指标，必须检查后置事件是否在前置事件之后。若口径是“注册后付费”，SQL 必须有等价约束：

```sql
pay_time >= register_time
```

如果 SQL 先按用户取 `MIN(pay_time)`，再和 `register_time` 比较，而没有在聚合前加入 `pay_time >= register_time`，标为 `HIGH` 或 `MEDIUM`，因为这可能漏算注册后仍然完成付费的用户。

## 输出格式

```yaml
sql_review:
  verdict: PASS | FAIL
  highest_severity: NONE | LOW | MEDIUM | HIGH
  summary: "一句话结论"
  findings:
    - id: R1
      severity: HIGH | MEDIUM | LOW
      check: reference_integrity | join_cardinality | metric_formula | time_filter | time_boundary | conversion_order | group_by | type_check | write_risk | performance | other
      location: "SQL 片段或行号"
      message: "问题描述"
      recommendation: "建议修复方向"
  notes:
    - "评审假设"
```

## 用户可见摘要

除了 YAML，必须输出：

```markdown
## SQL Review
- 结论：PASS / FAIL
- 最高风险：NONE / LOW / MEDIUM / HIGH
- 已检查：字段引用、join、GROUP BY、时间窗口、转化顺序、空值、类型、性能
- 主要风险：...
- 是否可交付：...
```

## 严重程度

- `HIGH`：会导致数字错误、执行失败、越权写入或违反策略，必须阻断。
- `MEDIUM`：大概率可跑，但有性能、稳定性或边界风险，需要用户接受。
- `LOW`：风格或可维护性问题。

只要存在 HIGH，`verdict` 就是 `FAIL`。只有 LOW/MEDIUM 时，可以把风险交给用户决定是否接受。

## 禁止行为

- 不要直接改 SQL；只输出发现和建议。
- 不要凭直觉审字段，必须对照 `sql_context`。
- 不要因为 SQL 能通过 guardrails 就跳过业务正确性审查。
- 不要忽略写入模式，尤其是 `INSERT OVERWRITE`。
