Files
SBrainCO/scripts/refresh_materialized_views.sh
T
freedakgmail a090fc7c19 fix: 修复API数据正确性问题
- 移除3个API的operating_expense IS NOT NULL过滤,改用COALESCE
  - /overview/store-profit-ranking: 93家门店全部纳入排名
  - /overview/profit-opportunity: 所有有营收门店纳入机会计算
  - /overview/profit-trend: LEFT JOIN替代INNER JOIN
- 重建v_store_operating_expense_monthly视图,去除硬编码_april视图
  - sales CTE改用mv_store_site_profile_monthly
  - food CTE改用mv_store_theoretical_actual_cost_monthly
  - 支持任意月份查询
- 修复人工优化和能源优化opportunity为负数问题
- 新增scripts/refresh_materialized_views.sh自动化刷新脚本
- 新增本体.md/API.md/原始数据级导入处理.md/物化视图更新.md/API数据检查报告.md
2026-08-11 19:25:49 +08:00

100 lines
4.3 KiB
Bash
Executable File

#!/bin/bash
# refresh_materialized_views.sh
# 数据导入后刷新所有物化视图并更新费用物化表
# 用法: bash scripts/refresh_materialized_views.sh [YYYY-MM-DD]
# 示例: bash scripts/refresh_materialized_views.sh 2026-04-01
set -e
MONTH_START="${1:-$(date -u +%Y-%m-01)}"
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
DB_USER="${DB_USER:-freedak}"
DB_NAME="${DB_NAME:-bill_query}"
echo "=========================================="
echo " 刷新物化视图"
echo " 月份: ${MONTH_START}"
echo " 数据库: ${DB_NAME}@${DB_HOST}:${DB_PORT}"
echo "=========================================="
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" <<EOF
-- 第一层:账单事实
REFRESH MATERIALIZED VIEW analytics.bill_fact;
SELECT 'bill_fact refreshed' AS status;
-- 第二层:门店评估
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;
SELECT 'core MVs refreshed' AS status;
-- 第三层:菜品分析
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;
SELECT 'dish MVs refreshed' AS status;
-- 第四层:门店深度分析
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;
SELECT 'store deep MVs refreshed' AS status;
-- 第五层:区域与选址
REFRESH MATERIALIZED VIEW analytics.mv_district_site_benchmark_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_site_segment_benchmark_monthly;
SELECT 'region MVs refreshed' AS status;
-- 库存成本
REFRESH MATERIALIZED VIEW analytics.mv_inventory_cost_classified_monthly;
SELECT 'inventory MV refreshed' AS status;
-- 费用物化表(从视图写入)
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 'expense table updated' AS status;
-- 验证
SELECT '=== 数据一致性验证 ===' AS header;
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}';
SELECT '=== 门店覆盖检查 ===' AS header;
SELECT r.store_code, r.store_name, r.received,
CASE WHEN e.sales_store_code IS NOT NULL THEN '有费用' ELSE '无费用' END AS expense_status
FROM analytics.mv_store_risk_rating_monthly r
LEFT JOIN analytics.mv_store_operating_expense_monthly e
ON r.store_code = e.sales_store_code AND e.report_month = '${MONTH_START}'
WHERE r.month_start = '${MONTH_START}' AND r.received > 0
AND e.sales_store_code IS NULL
ORDER BY r.received DESC;
EOF
echo "=========================================="
echo " 刷新完成!"
echo "=========================================="