25db0f3854
- 创建12个按月物化视图替代实时函数调用 - phase10: mv_dish_sku_summary_monthly, mv_dish_sku_abc_monthly - phase11: mv_store_risk_rating/platform_economics/category_mix/member_opportunity/benchmark_composite/deep_diagnosis/dish_basket/dish_store_summary/theoretical_actual_cost (全部_monthly) - 后端所有路由从 fn_xxx() 改为 mv_xxx_monthly WHERE month_start = - 新增 analytics.refresh_all_monthly_views() 刷新函数 - 优化 fn_dish_sku_summary: CTE物化避免重复调用 - 优化 fn_dish_sku_abc: CTE物化 fn_dish_sku_summary 只调用一次 - 优化 fn_dish_sales: 添加 dish_name IS NOT NULL 提前过滤
169 lines
9.0 KiB
PL/PgSQL
169 lines
9.0 KiB
PL/PgSQL
-- ============================================================
|
|
-- Phase 11: 全量物化视图 — 按月预计算所有慢函数
|
|
-- 数据导入后调用 analytics.refresh_all_monthly_views() 刷新
|
|
-- ============================================================
|
|
|
|
-- 1. mv_store_risk_rating_monthly
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_store_risk_rating_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_store_risk_rating_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_store_risk_rating(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_risk_rating_month_store ON analytics.mv_store_risk_rating_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_risk_rating_month ON analytics.mv_store_risk_rating_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 2. mv_store_platform_economics_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_store_platform_economics_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_store_platform_economics_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_store_platform_economics(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_platform_econ_month_store ON analytics.mv_store_platform_economics_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_platform_econ_month ON analytics.mv_store_platform_economics_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 3. mv_store_category_mix_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_store_category_mix_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_store_category_mix_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_store_category_mix(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_cat_mix_month_store ON analytics.mv_store_category_mix_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_cat_mix_month ON analytics.mv_store_category_mix_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 4. mv_store_member_opportunity_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_store_member_opportunity_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_store_member_opportunity_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_store_member_opportunity(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_member_opp_month_store ON analytics.mv_store_member_opportunity_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_member_opp_month ON analytics.mv_store_member_opportunity_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 5. mv_store_benchmark_composite_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_store_benchmark_composite_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_store_benchmark_composite_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_store_benchmark_composite(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_benchmark_month_store ON analytics.mv_store_benchmark_composite_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_benchmark_month ON analytics.mv_store_benchmark_composite_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 6. mv_store_deep_diagnosis_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_store_deep_diagnosis_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_store_deep_diagnosis_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_store_deep_diagnosis(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_deep_diag_month_store ON analytics.mv_store_deep_diagnosis_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_deep_diag_month ON analytics.mv_store_deep_diagnosis_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 7. mv_dish_basket_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_dish_basket_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_dish_basket_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_dish_basket(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_dish_basket_month ON analytics.mv_dish_basket_monthly (month_start, store_code, bill_no);
|
|
CREATE INDEX idx_mv_dish_basket_month_start ON analytics.mv_dish_basket_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 8. mv_dish_store_summary_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_dish_store_summary_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_dish_store_summary_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_dish_store_summary(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_dish_store_summary_month ON analytics.mv_dish_store_summary_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_dish_store_summary_month_start ON analytics.mv_dish_store_summary_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 9. mv_store_theoretical_actual_cost_monthly
|
|
-- ============================================================
|
|
DROP MATERIALIZED VIEW IF EXISTS analytics.mv_store_theoretical_actual_cost_monthly;
|
|
CREATE MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly AS
|
|
SELECT m.month_start::date AS month_start, r.*
|
|
FROM generate_series(
|
|
(SELECT date_trunc('month', min(closed_at))::date FROM analytics.bill_fact),
|
|
(SELECT date_trunc('month', max(closed_at))::date FROM analytics.bill_fact),
|
|
interval '1 month'
|
|
) AS m(month_start)
|
|
CROSS JOIN LATERAL analytics.fn_store_theoretical_actual_cost(m.month_start::date) r;
|
|
|
|
CREATE UNIQUE INDEX idx_mv_theor_actual_month_store ON analytics.mv_store_theoretical_actual_cost_monthly (month_start, store_code);
|
|
CREATE INDEX idx_mv_theor_actual_month ON analytics.mv_store_theoretical_actual_cost_monthly (month_start);
|
|
|
|
-- ============================================================
|
|
-- 刷新函数 — 数据导入后调用
|
|
-- ============================================================
|
|
CREATE OR REPLACE FUNCTION analytics.refresh_all_monthly_views()
|
|
RETURNS void
|
|
LANGUAGE plpgsql
|
|
AS $function$
|
|
BEGIN
|
|
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_summary_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_abc_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_store_risk_rating_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_store_platform_economics_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_store_category_mix_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_store_member_opportunity_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_store_benchmark_composite_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_store_deep_diagnosis_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_dish_basket_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_dish_store_summary_monthly;
|
|
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
|
|
END;
|
|
$function$;
|