a090fc7c19
- 移除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
100 lines
4.3 KiB
Bash
Executable File
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 "=========================================="
|