--- 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`。