# 15 · 技术参考:指标口径一致性分析 > 从数据溯源审计中提取的跨页面重复指标口径对比,以及已发现和待修复的问题清单。 ## 1. 跨页面核心指标口径对比 ### 1.1 营业收入(消费金额) | 页面 | 前端变量 | API | API字段 | 数据源表.字段 | |------|---------|-----|---------|-------------| | 总部驾驶舱 | `od?.consumption` | /overview | `consumption` | analytics.bill_fact.consumption | | 老板驾驶舱 | `od?.consumption` | /overview | `consumption` | 同上 | | 费用总览Tab | `ov.total_consumption` | /store-expense/overview | `total_consumption` | analytics.bill_fact.consumption | **口径:一致 ✅** ### 1.2 优惠 | 页面 | 前端变量 | API | API字段 | 数据源表.字段 | |------|---------|-----|---------|-------------| | 总部驾驶舱 | `od?.discount` | /overview | `discount` | analytics.bill_fact.discount_total | | 老板驾驶舱 | `od?.discount` | /overview | `discount` | 同上 | | 费用总览Tab | `ov.total_discount` | /store-expense/overview | `total_discount` | 同上 | **口径:一致 ✅** ### 1.3 实收 | 页面 | 前端变量 | API | API字段 | 数据源表.字段 | |------|---------|-----|---------|-------------| | 总部驾驶舱 | `od?.received` | /overview | `received` | analytics.bill_fact.received_total | | 老板驾驶舱 | `od?.received` | /overview | `received` | 同上 | | 费用总览Tab | `ov.total_received` | /store-expense/overview | `total_received` | analytics.mv_store_risk_rating_monthly.received | | 利润瀑布 | `wf.received` | /overview/profit-waterfall | `received` | analytics.mv_store_risk_rating_monthly.received | **口径:一致 ✅** — `bill_fact.received_total` 汇总和物化视图汇总结果相同。 ### 1.4 账单数 | 页面 | 前端变量 | API | API字段 | 数据源表.字段 | |------|---------|-----|---------|-------------| | 总部驾驶舱 | `od?.bill_count` | /overview | `bill_count` | analytics.bill_fact (count(*)) | | 老板驾驶舱 | `ex?.total_bills` | /store-expense/overview | `total_bills` | analytics.mv_store_risk_rating_monthly.bill_count | **口径:一致 ✅** ### 1.5 客单价 | 页面 | 计算方式 | 值 | |------|---------|-----| | 总部驾驶舱 | `avg(received_total)` from bill_fact | 38.29 | | 老板驾驶舱 | `sum(received)/sum(bill_count)` | 38.29 | **口径:一致 ✅** — 数学结果相同。 ### 1.6 门店贡献利润(实际) | 页面 | API | 计算方式 | 值 | |------|-----|---------|-----| | 总部驾驶舱 | /store-expense/overview | `sum(received) FILTER(费用匹配) - food_cost - operating_expense` | 6,982,110.42 | | 老板驾驶舱(指标卡) | 同上 | 同上 | 同上 | | 老板驾驶舱(瀑布图) | /overview/profit-waterfall | `sum(received) FILTER(has_expense) - food_cost - operating_expense` | 同上 | **口径:一致 ✅**(已修复) ### 1.7 食材成本 | 页面 | API | 计算方式 | |------|-----|---------| | 总部驾驶舱 | /store-expense/overview | `sum(actual_food_cost)` | | 老板驾驶舱(瀑布图) | /overview/profit-waterfall | `sum(COALESCE(actual_food_cost,0))` | | 费用总览Tab | /store-expense/overview | 同总部 | **口径:一致 ✅** — `sum(NULL)` 忽略 vs `sum(COALESCE(NULL,0))` 加0,结果相同。 ### 1.8 费用率 | 页面 | 计算方式 | 值 | |------|---------|-----| | 总部驾驶舱 | `sum(operating_expense)/matched_received*100` | 53.77% | | 老板驾驶舱(瀑布图) | `wf.total_expense/wf.received*100`(matched口径) | 53.77% | | 费用总览Tab | 同总部 | 53.77% | **口径:一致 ✅**(已修复) ### 1.9 门店风险分布 / P0+P1门店 / 盈利亏损数 | 指标 | 页面 | API | 数据源 | |------|------|-----|--------| | 风险分布 | 总部/老板 | /stores/risk | mv_store_risk_rating_monthly.risk_level | | P0/P1 | 总部/老板 | /stores/priority | mv_store_action_priority_deep_monthly | | 盈利/亏损 | 总部/老板 | /store-expense/overview | count FILTER(actual_store_contribution > 0) | **口径:一致 ✅** ## 2. 口径一致性保障原则 1. **同一指标多页面展示时,必须使用同一数据源**(物化视图或原始表,不能混用) 2. **分母口径必须一致**:如"费用率"分母必须统一为 matched_received(仅含费用匹配门店) 3. **FILTER vs COALESCE**:`sum(x) FILTER(WHERE has_expense)` 与 `sum(COALESCE(x,0))` 在无NULL行时结果相同,但语义不同——FILTER排除整行,COALESCE只替换NULL值 4. **物化视图 vs 原始表**:优先用物化视图,避免直接查原始表(性能差 + 可能stale不一致) 5. **新增页面时**:如果复用已有指标,必须检查数据源是否一致,避免口径分裂 ## 3. 已发现问题清单 ### 已修复 ✅ | # | 问题 | 位置 | 修复方式 | |---|------|------|---------| | 1 | 利润瀑布 store_contribution 口径不一致 | /overview/profit-waterfall | received等改为 `FILTER(WHERE has_expense)` | | 2 | 瀑布图费率分母不一致 | 前端除法 | received改为matched口径后分母一致 | | 3 | mv_overview_monthly 刷新缺失 | 刷新脚本 | 加入DELETE+INSERT步骤 | | 4 | 优惠率/毛利率/会员占比硬编码为0 | /overview API | 修正SQL计算 | | 5 | Schema前缀错误 | /channel API | 移除analytics.前缀 | | 6 | 列名不存在 | /stores/risk等 | SELECT * 或0 AS替代 | | 7 | 日期格式不匹配 | 考勤相关API | to_char改中文格式 | | 8 | 客流-人力匹配在岗人数不合理 | /situational-awareness/correlation | 改用打卡数据解析 | | 9 | 客流月度汇总vs日均未对齐 | 同上 | 客流除以30天 | ### 待确认 ⚠️ | # | 问题 | 位置 | 影响 | 建议 | |---|------|------|------|------| | 1 | KPI达成率利润口径不一致 | /analytics-enhanced/kpi | 利润率偏低~0.7pp | 分母改为matched_received | | 2 | store-profit-ranking COALESCE导致无费用门店排名异常 | /overview/store-profit-ranking | 利润TOP5可能含无费用门店 | 加FILTER(has_expense) | | 3 | StorePage公司均值硬编码 | StorePage.tsx:188 | 不随数据更新 | 改为API动态获取 | | 4 | StorePage scorecard直接查bill_records | /stores/:code | 可能与物化视图不一致 | 改用物化视图 | ## 4. 口径检查方法论 ### 4.1 新增指标时的检查流程 ``` 1. 该指标是否在其他页面已存在? → 是:检查数据源是否一致(表、字段、过滤条件) → 否:记录到溯源文档 2. 分子分母的过滤条件是否一致? → 如:费用率分母是否都用了matched_received 3. 是否用了物化视图? → 优先用物化视图,避免直接查原始表 4. 是否有NULL处理差异? → sum(x) vs sum(COALESCE(x,0)) 在有NULL行时结果不同 5. curl + psql 双向验证 → API返回值与直查数据库一致 ``` ### 4.2 定期口径审计 ``` 1. 运行溯源文档中的"跨页面对比"部分 2. 对每个指标,在所有出现的页面验证值是否一致 3. 不一致的,定位差异原因(数据源、过滤条件、计算方式) 4. 修复并更新文档 ```