docs: 归档历史文档 + 新增战略外脑实施方法论

- 归档根目录散落文档到 docs/20260812/ 和 docs/20260812-1/
- 新增 16-战略外脑实施方法论.md:七项能力、十二步工作法、AI与决策治理、成熟度和验收
- 新增 17-SBrainCO战略外脑建设对照表.md:方法论映射为领域模型、产品模块、API和分阶段待办
- 新增 调查表/战略外脑能力验收Checklist.csv:35项能力验收检查项
- 更新 01-总体框架与八步工作法.md:新增战略外脑扩展章节
- 更新 README.md:新增战略外脑体系导航

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
selfrelease
2026-08-12 22:28:51 +08:00
parent a0343294b6
commit 7ea6a2515f
56 changed files with 660 additions and 0 deletions
+302
View File
@@ -0,0 +1,302 @@
# 物化视图更新手册
## 一、物化视图依赖链
数据更新后必须按依赖顺序刷新物化视图,否则下游数据不一致。
```
bill_records (原始表)
▼ REFRESH
bill_fact (物化视图) ★ 第一层,最关键
├─▶ mv_daily_revenue
├─▶ mv_store_risk_rating_monthly ★ 门店评估基础
├─▶ mv_dish_sku_abc_monthly
├─▶ mv_dish_sku_summary_monthly
├─▶ mv_dish_store_summary_monthly
├─▶ mv_dish_basket_monthly
├─▶ mv_dish_pair_summary_monthly
├─▶ mv_store_action_priority_deep_monthly
├─▶ mv_store_area_efficiency_monthly
├─▶ mv_store_benchmark_composite_monthly
├─▶ mv_store_category_mix_monthly
├─▶ mv_store_deep_diagnosis_monthly
├─▶ mv_store_member_opportunity_monthly
├─▶ mv_store_overlap_risk_monthly
├─▶ mv_store_platform_economics_monthly
├─▶ mv_store_site_profile_monthly
├─▶ mv_store_site_replication_monthly
├─▶ mv_store_repeat_summary_monthly
├─▶ mv_district_site_benchmark_monthly
├─▶ mv_site_segment_benchmark_monthly
└─▶ mv_store_theoretical_actual_cost_monthly ★ 门店成本
inventory_cost_records (原始表)
▼ REFRESH
mv_inventory_cost_classified_monthly
operating_expense_records (原始表)
▼ VIEW (无需刷新)
v_operating_expense_unit_monthly
▼ VIEW (无需刷新)
v_store_operating_expense_monthly (按 sales_store_code 聚合)
▼ INSERT/UPDATE (需手动操作)
mv_store_operating_expense_monthly (物化表)
```
---
## 二、刷新命令清单
### 2.1 账单数据更新后(必刷)
```sql
-- ★ 第一优先级:bill_fact 是所有分析的基础
REFRESH MATERIALIZED VIEW analytics.bill_fact;
-- ★ 第二优先级:门店评估相关
REFRESH MATERIALIZED VIEW analytics.mv_store_risk_rating_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
-- 第三优先级:菜品分析
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_abc_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_store_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_basket_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_pair_summary_monthly;
-- 第四优先级:门店深度分析
REFRESH MATERIALIZED VIEW analytics.mv_store_action_priority_deep_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_area_efficiency_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_benchmark_composite_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_category_mix_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_deep_diagnosis_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_member_opportunity_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_overlap_risk_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_platform_economics_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_profile_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_replication_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_repeat_summary_monthly;
-- 第五优先级:日度与区域
REFRESH MATERIALIZED VIEW analytics.mv_daily_revenue;
REFRESH MATERIALIZED VIEW analytics.mv_district_site_benchmark_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_site_segment_benchmark_monthly;
```
### 2.2 库存成本数据更新后
```sql
REFRESH MATERIALIZED VIEW analytics.mv_inventory_cost_classified_monthly;
-- 理论vs实际成本也依赖库存数据
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
```
### 2.3 费用数据更新后
```sql
-- v_operating_expense_unit_monthly 和 v_store_operating_expense_monthly 是普通视图,无需刷新
-- 但 mv_store_operating_expense_monthly 是物化表,需要手动更新:
-- 方法1:删除+插入(推荐,简单可靠)
DELETE FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly WHERE report_month = '2026-04-01';
-- 方法2:全量重建
TRUNCATE analytics.mv_store_operating_expense_monthly;
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly;
```
---
## 三、一键刷新脚本
```bash
#!/bin/bash
# refresh_all_mv.sh - 刷新所有物化视图
# 用法: bash refresh_all_mv.sh [month] (默认 2026-04)
MONTH=${1:-2026-04}
MONTH_START="${MONTH}-01"
psql -h localhost -p 5432 -U freedak -d bill_query <<EOF
-- 第一层
REFRESH MATERIALIZED VIEW analytics.bill_fact;
-- 第二层
REFRESH MATERIALIZED VIEW analytics.mv_store_risk_rating_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_daily_revenue;
-- 第三层
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_abc_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_store_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_basket_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_pair_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_action_priority_deep_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_area_efficiency_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_benchmark_composite_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_category_mix_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_deep_diagnosis_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_member_opportunity_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_overlap_risk_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_platform_economics_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_profile_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_replication_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_repeat_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_district_site_benchmark_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_site_segment_benchmark_monthly;
-- 库存成本
REFRESH MATERIALIZED VIEW analytics.mv_inventory_cost_classified_monthly;
-- 费用物化表
DELETE FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '${MONTH_START}';
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly WHERE report_month = '${MONTH_START}';
-- 验证
SELECT 'bill_fact' AS source, count(DISTINCT store_code) AS stores, round(sum(received_total)::numeric,2) AS received
FROM analytics.bill_fact WHERE closed_at >= '${MONTH_START}' AND closed_at < ('${MONTH_START}'::date + interval '1 month')
UNION ALL
SELECT 'risk_rating', count(*), round(sum(received)::numeric,2)
FROM analytics.mv_store_risk_rating_monthly WHERE month_start = '${MONTH_START}'
UNION ALL
SELECT 'theo_cost', count(*), round(sum(sales_received)::numeric,2)
FROM analytics.mv_store_theoretical_actual_cost_monthly WHERE month_start = '${MONTH_START}'
UNION ALL
SELECT 'op_expense', count(*), round(sum(received)::numeric,2)
FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '${MONTH_START}';
EOF
```
---
## 四、物化视图 vs 普通视图 vs 物化表
| 类型 | 刷新方式 | 示例 | 说明 |
|------|----------|------|------|
| 物化视图 (Materialized View) | `REFRESH MATERIALIZED VIEW` | `bill_fact`, `mv_store_risk_rating_monthly` | 数据快照,需手动刷新 |
| 普通视图 (View) | 实时查询,无需刷新 | `v_store_operating_expense_monthly`, `v_operating_expense_account_monthly` | 每次查询实时计算 |
| 物化表 (Table) | `INSERT/UPDATE/DELETE` | `mv_store_operating_expense_monthly` | 物理表,需手动写入 |
### 判断方法
```sql
-- 查看对象类型
SELECT relname, relkind
FROM pg_class
WHERE relname LIKE 'mv_%' OR relname LIKE 'v_%'
AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'analytics');
-- relkind 含义:
-- 'm' = 物化视图 (需要 REFRESH)
-- 'v' = 普通视图 (无需刷新)
-- 'r' = 普通表 (需要 INSERT/UPDATE)
```
---
## 五、常见问题
### 5.1 数据不一致
**症状**: API返回的门店数少于实际门店数,或实收合计与 bill_fact 不一致
**原因**: 导入新数据后未刷新物化视图
**修复**: 执行上述刷新命令
### 5.2 费用未纳入门店评估
**症状**: 某门店在评估列表中缺失或费用为0
**原因**:
1. `operating_expense_store_mapping``sales_store_code` 未设置
2. `include_in_operating_analysis` 标志为 false
3. `mv_store_operating_expense_monthly` 物化表未更新
**修复**:
```sql
-- 检查映射
SELECT * FROM operating_expense_store_mapping WHERE cost_unit_source_name ILIKE '%门店名%';
-- 更新映射
UPDATE operating_expense_store_mapping
SET sales_store_code = '0022', include_in_operating_analysis = true
WHERE cost_unit_source_name = '哈马尔罕大钟寺店';
-- 刷新物化表
DELETE FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly WHERE report_month = '2026-04-01';
```
### 5.3 费用重复行
**症状**: 同一门店在 `mv_store_operating_expense_monthly` 中出现多行
**原因**: 多个费用单位映射到同一 `sales_store_code`,但视图未按 `sales_store_code` 聚合
**修复**: 确认 `v_store_operating_expense_monthly` 视图定义包含 `expense_agg` CTE,按 `sales_store_code` GROUP BY
### 5.4 固定月份物化视图
**问题**: `*_april` 系列物化视图硬编码2026年4月,不支持其他月份
**影响**: 5月数据需要创建新的 `*_may` 系列物化视图,或修改为通用月份
**当前状态**: `v_store_operating_expense_monthly` 视图中 sales/food/loc CTE 引用了 `v_store_site_profile_april``v_store_theoretical_actual_cost_april`,这些是4月专用视图
---
## 六、数据一致性验证
刷新后执行以下验证:
```sql
-- 1. 门店数一致性
SELECT 'bill_fact' AS src, count(DISTINCT store_code) AS stores
FROM analytics.bill_fact
WHERE closed_at >= '2026-04-01' AND closed_at < '2026-05-01'
UNION ALL
SELECT 'risk_rating', count(*)
FROM analytics.mv_store_risk_rating_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'theo_cost', count(*)
FROM analytics.mv_store_theoretical_actual_cost_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'op_expense', count(*)
FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
-- 2. 实收一致性
SELECT 'bill_fact' AS src, round(sum(received_total)::numeric,2) AS received
FROM analytics.bill_fact
WHERE closed_at >= '2026-04-01' AND closed_at < '2026-05-01'
UNION ALL
SELECT 'risk_rating', round(sum(received)::numeric,2)
FROM analytics.mv_store_risk_rating_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'theo_cost', round(sum(sales_received)::numeric,2)
FROM analytics.mv_store_theoretical_actual_cost_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'op_expense', round(sum(received)::numeric,2)
FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
-- 3. 差异门店排查
SELECT store_code, store_name, received
FROM analytics.mv_store_risk_rating_monthly
WHERE month_start = '2026-04-01' AND received > 0
AND store_code NOT IN (
SELECT DISTINCT store_code FROM analytics.mv_store_operating_expense_monthly
WHERE report_month = '2026-04-01'
);
```