-- ============================================================
-- 10_materialize_slow_views.sql
-- 将门店详情页慢视图转为物化视图，加 store_code 索引
-- 预期：/stores/:code 从 ~15s 降至 <100ms
-- ============================================================

-- ============================================================
-- Step 1: 依赖视图按逆序 DROP
-- ============================================================
DROP VIEW IF EXISTS analytics.v_store_execution_priority;
DROP VIEW IF EXISTS analytics.v_store_deep_diagnosis_april;
DROP VIEW IF EXISTS analytics.v_store_benchmark_composite;
DROP VIEW IF EXISTS analytics.v_store_action_list;

-- ============================================================
-- Step 2: 基础视图 → 物化视图
-- ============================================================

-- 2a. v_store_platform_economics
DROP VIEW IF EXISTS analytics.v_store_platform_economics;
CREATE MATERIALIZED VIEW analytics.v_store_platform_economics AS
 SELECT NULLIF(bill_records.c002, ''::text) AS store_code,
    NULLIF(bill_records.c003, ''::text) AS store_name,
    sum(COALESCE(NULLIF(bill_records.c151, ''::text)::numeric, 0::numeric)) AS meituan_received,
    sum(COALESCE(NULLIF(bill_records.c101, ''::text)::numeric, 0::numeric)) AS meituan_discount,
    sum(COALESCE(NULLIF(bill_records.c097, ''::text)::numeric, 0::numeric)) AS meituan_commission,
    sum(COALESCE(NULLIF(bill_records.c152, ''::text)::numeric, 0::numeric)) AS taobao_received,
    sum(COALESCE(NULLIF(bill_records.c102, ''::text)::numeric, 0::numeric)) AS taobao_discount,
    sum(COALESCE(NULLIF(bill_records.c098, ''::text)::numeric, 0::numeric)) AS taobao_commission,
    sum(COALESCE(NULLIF(bill_records.c150, ''::text)::numeric, 0::numeric)) AS jd_received,
    sum(COALESCE(NULLIF(bill_records.c099, ''::text)::numeric, 0::numeric)) AS jd_discount,
    sum(COALESCE(NULLIF(bill_records.c100, ''::text)::numeric, 0::numeric)) AS jd_commission,
    round((sum(COALESCE(NULLIF(bill_records.c101, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c097, ''::text)::numeric, 0::numeric))) / NULLIF(sum(COALESCE(NULLIF(bill_records.c151, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c101, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c097, ''::text)::numeric, 0::numeric)), 0::numeric) * 100::numeric, 2) AS meituan_cost_rate_pct,
    round((sum(COALESCE(NULLIF(bill_records.c102, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c098, ''::text)::numeric, 0::numeric))) / NULLIF(sum(COALESCE(NULLIF(bill_records.c152, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c102, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c098, ''::text)::numeric, 0::numeric)), 0::numeric) * 100::numeric, 2) AS taobao_cost_rate_pct,
    round((sum(COALESCE(NULLIF(bill_records.c099, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c100, ''::text)::numeric, 0::numeric))) / NULLIF(sum(COALESCE(NULLIF(bill_records.c150, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c099, ''::text)::numeric, 0::numeric)) + sum(COALESCE(NULLIF(bill_records.c100, ''::text)::numeric, 0::numeric)), 0::numeric) * 100::numeric, 2) AS jd_cost_rate_pct
   FROM bill_records
  WHERE NULLIF(bill_records.c005, ''::text) IS NOT NULL
  GROUP BY (NULLIF(bill_records.c002, ''::text)), (NULLIF(bill_records.c003, ''::text))
  WITH DATA;
CREATE UNIQUE INDEX IF NOT EXISTS idx_mv_platform_economics_store ON analytics.v_store_platform_economics (store_code);

-- 2b. v_store_category_mix
DROP VIEW IF EXISTS analytics.v_store_category_mix;
CREATE MATERIALIZED VIEW analytics.v_store_category_mix AS
 SELECT NULLIF(bill_records.c002, ''::text) AS store_code,
    NULLIF(bill_records.c003, ''::text) AS store_name,
    sum(COALESCE(NULLIF(bill_records.c009, ''::text)::numeric, 0::numeric)) AS consumption,
    sum(COALESCE(NULLIF(bill_records.c010, ''::text)::numeric, 0::numeric)) AS lanzhou_noodle,
    sum(COALESCE(NULLIF(bill_records.c016, ''::text)::numeric, 0::numeric)) AS western_staple,
    sum(COALESCE(NULLIF(bill_records.c027, ''::text)::numeric, 0::numeric)) AS delivery_package,
    sum(COALESCE(NULLIF(bill_records.c013, ''::text)::numeric, 0::numeric)) AS night_bbq,
    sum(COALESCE(NULLIF(bill_records.c015, ''::text)::numeric, 0::numeric)) AS cold_dishes,
    sum(COALESCE(NULLIF(bill_records.c019, ''::text)::numeric, 0::numeric)) AS silk_road_food,
    round(sum(COALESCE(NULLIF(bill_records.c010, ''::text)::numeric, 0::numeric)) / NULLIF(sum(COALESCE(NULLIF(bill_records.c009, ''::text)::numeric, 0::numeric)), 0::numeric) * 100::numeric, 2) AS noodle_share_pct,
    round(sum(COALESCE(NULLIF(bill_records.c027, ''::text)::numeric, 0::numeric)) / NULLIF(sum(COALESCE(NULLIF(bill_records.c009, ''::text)::numeric, 0::numeric)), 0::numeric) * 100::numeric, 2) AS delivery_package_share_pct,
    round(GREATEST(sum(COALESCE(NULLIF(bill_records.c010, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c016, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c027, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c013, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c015, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c019, ''::text)::numeric, 0::numeric))) / NULLIF(sum(COALESCE(NULLIF(bill_records.c009, ''::text)::numeric, 0::numeric)), 0::numeric) * 100::numeric, 2) AS top_category_share_pct,
        CASE GREATEST(sum(COALESCE(NULLIF(bill_records.c010, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c016, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c027, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c013, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c015, ''::text)::numeric, 0::numeric)), sum(COALESCE(NULLIF(bill_records.c019, ''::text)::numeric, 0::numeric)))
            WHEN sum(COALESCE(NULLIF(bill_records.c010, ''::text)::numeric, 0::numeric)) THEN '兰州牛肉面'::text
            WHEN sum(COALESCE(NULLIF(bill_records.c016, ''::text)::numeric, 0::numeric)) THEN '西部主食'::text
            WHEN sum(COALESCE(NULLIF(bill_records.c027, ''::text)::numeric, 0::numeric)) THEN '外卖套餐'::text
            WHEN sum(COALESCE(NULLIF(bill_records.c013, ''::text)::numeric, 0::numeric)) THEN '夜市烧烤'::text
            WHEN sum(COALESCE(NULLIF(bill_records.c015, ''::text)::numeric, 0::numeric)) THEN '爽口凉菜'::text
            ELSE '丝路美食'::text
        END AS top_category
   FROM bill_records
  WHERE NULLIF(bill_records.c005, ''::text) IS NOT NULL
  GROUP BY (NULLIF(bill_records.c002, ''::text)), (NULLIF(bill_records.c003, ''::text))
  WITH DATA;
CREATE UNIQUE INDEX IF NOT EXISTS idx_mv_category_mix_store ON analytics.v_store_category_mix (store_code);

-- 2c. v_store_benchmark
DROP VIEW IF EXISTS analytics.v_store_benchmark;
CREATE MATERIALIZED VIEW analytics.v_store_benchmark AS
 WITH eligible AS (
         SELECT v_store_risk_rating.store_code,
            v_store_risk_rating.store_name,
            v_store_risk_rating.bill_count,
            v_store_risk_rating.active_days,
            v_store_risk_rating.received,
            v_store_risk_rating.avg_daily_received,
            v_store_risk_rating.avg_bill_value,
            v_store_risk_rating.avg_guest_value,
            v_store_risk_rating.discount_rate_pct,
            v_store_risk_rating.theoretical_margin_pct,
            v_store_risk_rating.member_bill_share_pct,
            v_store_risk_rating.anomaly_rate_pct,
            v_store_risk_rating.risk_level,
            v_store_risk_rating.primary_issue
           FROM analytics.v_store_risk_rating
          WHERE v_store_risk_rating.active_days >= 25 AND v_store_risk_rating.bill_count >= 5000
        ), stats AS (
         SELECT percentile_cont(0.25::double precision) WITHIN GROUP (ORDER BY (eligible.avg_daily_received::double precision)) AS revenue_p25,
            percentile_cont(0.50::double precision) WITHIN GROUP (ORDER BY (eligible.avg_daily_received::double precision)) AS revenue_p50,
            percentile_cont(0.75::double precision) WITHIN GROUP (ORDER BY (eligible.avg_daily_received::double precision)) AS revenue_p75,
            percentile_cont(0.50::double precision) WITHIN GROUP (ORDER BY (eligible.theoretical_margin_pct::double precision)) AS margin_p50,
            percentile_cont(0.75::double precision) WITHIN GROUP (ORDER BY (eligible.theoretical_margin_pct::double precision)) AS margin_p75,
            percentile_cont(0.75::double precision) WITHIN GROUP (ORDER BY (eligible.discount_rate_pct::double precision)) AS discount_p75
           FROM eligible
        ), base AS (
         SELECT e.store_code,
            e.store_name,
            e.bill_count,
            e.active_days,
            e.received,
            e.avg_daily_received,
            e.avg_bill_value,
            e.avg_guest_value,
            e.discount_rate_pct,
            e.theoretical_margin_pct,
            e.member_bill_share_pct,
            e.anomaly_rate_pct,
            e.risk_level,
            e.primary_issue,
            s.revenue_p25,
            s.revenue_p50,
            s.revenue_p75,
            s.margin_p50,
            s.margin_p75,
            s.discount_p75
           FROM eligible e
             CROSS JOIN stats s
        )
 SELECT base.store_code,
    base.store_name,
    base.bill_count,
    base.active_days,
    base.received,
    base.avg_daily_received,
    base.avg_bill_value,
    base.avg_guest_value,
    base.discount_rate_pct,
    base.theoretical_margin_pct,
    base.member_bill_share_pct,
    base.anomaly_rate_pct,
    base.risk_level,
    base.primary_issue,
    base.revenue_p25,
    base.revenue_p50,
    base.revenue_p75,
    base.margin_p50,
    base.margin_p75,
    base.discount_p75,
        CASE
            WHEN base.avg_daily_received::double precision >= base.revenue_p75 AND base.theoretical_margin_pct::double precision >= base.margin_p50 THEN '明星门店'::text
            WHEN base.avg_daily_received::double precision >= base.revenue_p75 AND base.theoretical_margin_pct::double precision < base.margin_p50 THEN '规模承压'::text
            WHEN base.avg_daily_received::double precision < base.revenue_p75 AND base.theoretical_margin_pct::double precision >= base.margin_p75 THEN '高效潜力'::text
            WHEN base.avg_daily_received::double precision <= base.revenue_p25 OR base.theoretical_margin_pct < 68::numeric OR base.discount_rate_pct::double precision > base.discount_p75 THEN '重点改善'::text
            ELSE '稳健经营'::text
        END AS management_quadrant,
    round(GREATEST(base.received / NULLIF(1::numeric - base.discount_rate_pct / 100::numeric, 0::numeric) * (base.discount_rate_pct - 20.23) / 100::numeric, 0::numeric), 2) AS discount_saving_to_company_avg,
    round(GREATEST(base.received * 0.7092 - base.received * base.theoretical_margin_pct / 100::numeric, 0::numeric), 2) AS profit_uplift_to_company_margin
 FROM base
 WITH DATA;
CREATE UNIQUE INDEX IF NOT EXISTS idx_mv_benchmark_store ON analytics.v_store_benchmark (store_code);

-- ============================================================
-- Step 3: 组合视图 → 物化视图
-- ============================================================

-- 3a. v_store_action_list (joins benchmark + category_mix + platform_economics)
CREATE MATERIALIZED VIEW analytics.v_store_action_list AS
 SELECT b.store_code,
    b.store_name,
    b.management_quadrant,
    b.risk_level,
    b.primary_issue,
    b.received,
    b.avg_daily_received,
    b.avg_bill_value,
    b.discount_rate_pct,
    b.theoretical_margin_pct,
    b.anomaly_rate_pct,
    b.member_bill_share_pct,
    b.discount_saving_to_company_avg,
    b.profit_uplift_to_company_margin,
    c.top_category,
    c.top_category_share_pct,
    c.delivery_package_share_pct,
    p.meituan_cost_rate_pct,
    p.taobao_cost_rate_pct,
    p.jd_cost_rate_pct
   FROM analytics.v_store_benchmark b
      LEFT JOIN analytics.v_store_category_mix c USING (store_code, store_name)
      LEFT JOIN analytics.v_store_platform_economics p USING (store_code, store_name)
  WITH DATA;
CREATE UNIQUE INDEX IF NOT EXISTS idx_mv_action_list_store ON analytics.v_store_action_list (store_code);

-- 3b. v_store_execution_priority (joins action_list + meal + member + zero_bill)
CREATE MATERIALIZED VIEW analytics.v_store_execution_priority AS
 WITH meal AS (
         SELECT v_store_meal_opportunity.store_code,
            sum(v_store_meal_opportunity.avg_bill_uplift_scenario) AS meal_uplift_scenario
           FROM analytics.v_store_meal_opportunity
          WHERE v_store_meal_opportunity.bill_count >= 500
          GROUP BY v_store_meal_opportunity.store_code
        ), zero_bill AS (
         SELECT v_zero_received_detail.store_code,
            count(*) AS zero_received_bills,
            count(*) FILTER (WHERE v_zero_received_detail.zero_received_type = '优惠不足但无实收'::text) AS unexplained_zero_bills
           FROM analytics.v_zero_received_detail
          GROUP BY v_zero_received_detail.store_code
        )
 SELECT a.store_code,
    a.store_name,
    a.management_quadrant,
    a.risk_level,
    a.primary_issue,
    a.received,
    a.avg_daily_received,
    a.avg_bill_value,
    a.discount_rate_pct,
    a.theoretical_margin_pct,
    a.anomaly_rate_pct,
    a.member_bill_share_pct,
    a.discount_saving_to_company_avg,
    a.profit_uplift_to_company_margin,
    a.top_category,
    a.top_category_share_pct,
    a.delivery_package_share_pct,
    a.meituan_cost_rate_pct,
    a.taobao_cost_rate_pct,
    a.jd_cost_rate_pct,
    round(COALESCE(m.meal_uplift_scenario, 0::numeric), 2) AS meal_uplift_scenario,
    mo.member_share_pct,
    mo.conversion_bill_scenario,
    mo.revenue_uplift_scenario AS member_revenue_uplift_scenario,
    COALESCE(z.zero_received_bills, 0::bigint) AS zero_received_bills,
    COALESCE(z.unexplained_zero_bills, 0::bigint) AS unexplained_zero_bills
   FROM analytics.v_store_action_list a
     LEFT JOIN meal m USING (store_code)
     LEFT JOIN analytics.v_store_member_opportunity mo USING (store_code, store_name)
     LEFT JOIN zero_bill z USING (store_code)
  WITH DATA;
CREATE UNIQUE INDEX IF NOT EXISTS idx_mv_execution_priority_store ON analytics.v_store_execution_priority (store_code);

-- ============================================================
-- Step 4: 重建依赖普通视图（基于物化视图，查询会走索引）
-- ============================================================

-- 4a. v_store_benchmark_composite
CREATE OR REPLACE VIEW analytics.v_store_benchmark_composite AS
 WITH eligible AS (
         SELECT b.store_code,
            b.store_name,
            b.received,
            b.avg_daily_received,
            b.avg_bill_value,
            b.discount_rate_pct,
            b.theoretical_margin_pct,
            b.anomaly_rate_pct,
            b.member_bill_share_pct,
            r.identified_members,
            r.repeat_rate_pct,
            r.avg_orders,
            r.repeat_revenue_share_pct,
            p.meituan_cost_rate_pct,
            p.taobao_cost_rate_pct,
            p.jd_cost_rate_pct
           FROM analytics.v_store_benchmark b
             JOIN analytics.v_store_repeat_summary_monthly r ON r.store_code = b.store_code AND r.month_start = '2026-04-01'::date
             LEFT JOIN analytics.v_store_platform_economics p ON p.store_code = b.store_code
          WHERE b.theoretical_margin_pct >= 60::numeric AND b.theoretical_margin_pct <= 80::numeric AND r.identified_members >= 500
        ), scored AS (
         SELECT eligible.store_code,
            eligible.store_name,
            eligible.received,
            eligible.avg_daily_received,
            eligible.avg_bill_value,
            eligible.discount_rate_pct,
            eligible.theoretical_margin_pct,
            eligible.anomaly_rate_pct,
            eligible.member_bill_share_pct,
            eligible.identified_members,
            eligible.repeat_rate_pct,
            eligible.avg_orders,
            eligible.repeat_revenue_share_pct,
            eligible.meituan_cost_rate_pct,
            eligible.taobao_cost_rate_pct,
            eligible.jd_cost_rate_pct,
            percent_rank() OVER (ORDER BY eligible.avg_daily_received) AS revenue_score,
            percent_rank() OVER (ORDER BY eligible.theoretical_margin_pct) AS margin_score,
            1::double precision - percent_rank() OVER (ORDER BY eligible.discount_rate_pct) AS discount_score,
            1::double precision - percent_rank() OVER (ORDER BY eligible.anomaly_rate_pct) AS anomaly_score,
            percent_rank() OVER (ORDER BY eligible.repeat_rate_pct) AS repeat_score
           FROM eligible
        )
 SELECT scored.store_code,
    scored.store_name,
    scored.received,
    scored.avg_daily_received,
    scored.avg_bill_value,
    scored.discount_rate_pct,
    scored.theoretical_margin_pct,
    scored.anomaly_rate_pct,
    scored.member_bill_share_pct,
    scored.identified_members,
    scored.repeat_rate_pct,
    scored.avg_orders,
    scored.repeat_revenue_share_pct,
    scored.meituan_cost_rate_pct,
    scored.taobao_cost_rate_pct,
    scored.jd_cost_rate_pct,
    scored.revenue_score,
    scored.margin_score,
    scored.discount_score,
    scored.anomaly_score,
    scored.repeat_score,
    round(((scored.revenue_score * 0.25::double precision + scored.margin_score * 0.25::double precision + scored.discount_score * 0.20::double precision + scored.anomaly_score * 0.15::double precision + scored.repeat_score * 0.15::double precision) * 100::double precision)::numeric, 2) AS benchmark_score
   FROM scored;

-- 4b. v_store_deep_diagnosis_april
CREATE OR REPLACE VIEW analytics.v_store_deep_diagnosis_april AS
 WITH store_base AS (
         SELECT s.store_code,
            s.store_name,
            s.bill_count,
            s.active_days,
            s.received,
            s.avg_daily_received,
            s.avg_bill_value,
            s.discount_rate_pct,
            s.theoretical_margin_pct,
            s.member_bill_share_pct,
            d.items_per_bill,
            d.skus_per_bill,
            d.delivery_bill_share_pct,
            d.noodle_snack_attach_pct,
            d.noodle_drink_attach_pct,
            d.noodle_cold_attach_pct,
            d.combo_bill_share_pct,
            c.theoretical_cost,
            c.actual_food_cost,
            c.food_cost_variance,
            c.theoretical_cost_rate_pct,
            c.actual_food_cost_rate_pct,
            c.variance_to_theoretical_pct,
            c.comparison_status,
            c.variance_level,
            b.identified_members,
            b.repeat_rate_pct,
            b.repeat_revenue_share_pct,
            b.benchmark_score,
            p.meituan_received,
            p.taobao_received,
            p.jd_received,
            round((COALESCE(p.meituan_discount, 0::numeric) + COALESCE(p.taobao_discount, 0::numeric) + COALESCE(p.jd_discount, 0::numeric) + COALESCE(p.meituan_commission, 0::numeric) + COALESCE(p.taobao_commission, 0::numeric) + COALESCE(p.jd_commission, 0::numeric)) / NULLIF(COALESCE(p.meituan_received, 0::numeric) + COALESCE(p.taobao_received, 0::numeric) + COALESCE(p.jd_received, 0::numeric) + COALESCE(p.meituan_discount, 0::numeric) + COALESCE(p.taobao_discount, 0::numeric) + COALESCE(p.jd_discount, 0::numeric) + COALESCE(p.meituan_commission, 0::numeric) + COALESCE(p.taobao_commission, 0::numeric) + COALESCE(p.jd_commission, 0::numeric), 0::numeric) * 100::numeric, 2) AS combined_platform_cost_rate_pct,
                CASE
                    WHEN s.store_name ~ '机场|火锅|商城|快手|哈马尔罕'::text THEN '特殊业态'::text
                    ELSE '标准门店'::text
                END AS business_type
           FROM analytics.v_store_scorecard s
             LEFT JOIN analytics.dish_store_summary_april d USING (store_code)
             LEFT JOIN analytics.v_store_theoretical_actual_cost_april c USING (store_code)
             LEFT JOIN analytics.v_store_benchmark_composite b USING (store_code)
             LEFT JOIN analytics.v_store_platform_economics p USING (store_code)
        ), tiered AS (
         SELECT store_base.store_code,
            store_base.store_name,
            store_base.bill_count,
            store_base.active_days,
            store_base.received,
            store_base.avg_daily_received,
            store_base.avg_bill_value,
            store_base.discount_rate_pct,
            store_base.theoretical_margin_pct,
            store_base.member_bill_share_pct,
            store_base.items_per_bill,
            store_base.skus_per_bill,
            store_base.delivery_bill_share_pct,
            store_base.noodle_snack_attach_pct,
            store_base.noodle_drink_attach_pct,
            store_base.noodle_cold_attach_pct,
            store_base.combo_bill_share_pct,
            store_base.theoretical_cost,
            store_base.actual_food_cost,
            store_base.food_cost_variance,
            store_base.theoretical_cost_rate_pct,
            store_base.actual_food_cost_rate_pct,
            store_base.variance_to_theoretical_pct,
            store_base.comparison_status,
            store_base.variance_level,
            store_base.identified_members,
            store_base.repeat_rate_pct,
            store_base.repeat_revenue_share_pct,
            store_base.benchmark_score,
            store_base.meituan_received,
            store_base.taobao_received,
            store_base.jd_received,
            store_base.combined_platform_cost_rate_pct,
            store_base.business_type,
                CASE
                    WHEN store_base.business_type = '特殊业态'::text THEN '特殊业态'::text
                    WHEN percent_rank() OVER (PARTITION BY store_base.business_type ORDER BY store_base.received) >= 0.67::double precision THEN '高规模'::text
                    WHEN percent_rank() OVER (PARTITION BY store_base.business_type ORDER BY store_base.received) >= 0.33::double precision THEN '中规模'::text
                    ELSE '低规模'::text
                END AS scale_tier
           FROM store_base
        )
 SELECT tiered.store_code,
    tiered.store_name,
    tiered.bill_count,
    tiered.active_days,
    tiered.received,
    tiered.avg_daily_received,
    tiered.avg_bill_value,
    tiered.discount_rate_pct,
    tiered.theoretical_margin_pct,
    tiered.member_bill_share_pct,
    tiered.items_per_bill,
    tiered.skus_per_bill,
    tiered.delivery_bill_share_pct,
    tiered.noodle_snack_attach_pct,
    tiered.noodle_drink_attach_pct,
    tiered.noodle_cold_attach_pct,
    tiered.combo_bill_share_pct,
    tiered.theoretical_cost,
    tiered.actual_food_cost,
    tiered.food_cost_variance,
    tiered.theoretical_cost_rate_pct,
    tiered.actual_food_cost_rate_pct,
    tiered.variance_to_theoretical_pct,
    tiered.comparison_status,
    tiered.variance_level,
    tiered.identified_members,
    tiered.repeat_rate_pct,
    tiered.repeat_revenue_share_pct,
    tiered.benchmark_score,
    tiered.meituan_received,
    tiered.taobao_received,
    tiered.jd_received,
    tiered.combined_platform_cost_rate_pct,
    tiered.business_type,
    tiered.scale_tier,
        CASE
            WHEN tiered.comparison_status = '可比'::text AND tiered.variance_to_theoretical_pct >= 20::numeric THEN 1
            ELSE 0
        END +
        CASE
            WHEN tiered.discount_rate_pct >= 23.02 THEN 1
            ELSE 0
        END +
        CASE
            WHEN tiered.theoretical_margin_pct < 70::numeric THEN 1
            ELSE 0
        END +
        CASE
            WHEN tiered.identified_members >= 500 AND tiered.repeat_rate_pct < 30::numeric THEN 1
            ELSE 0
        END +
        CASE
            WHEN tiered.combined_platform_cost_rate_pct >= 40::numeric THEN 1
            ELSE 0
        END +
        CASE
            WHEN tiered.noodle_drink_attach_pct < 12::numeric THEN 1
            ELSE 0
        END AS problem_count,
    concat_ws('＋'::text,
        CASE
            WHEN tiered.comparison_status = '理论成本口径异常'::text THEN '成本口径异常'::text
            ELSE NULL::text
        END,
        CASE
            WHEN tiered.comparison_status = '可比'::text AND tiered.variance_to_theoretical_pct >= 20::numeric THEN '实际成本严重超耗'::text
            ELSE NULL::text
        END,
        CASE
            WHEN tiered.discount_rate_pct >= 23.02 THEN '优惠偏高'::text
            ELSE NULL::text
        END,
        CASE
            WHEN tiered.theoretical_margin_pct < 70::numeric THEN '理论毛利偏低'::text
            ELSE NULL::text
        END,
        CASE
            WHEN tiered.identified_members >= 500 AND tiered.repeat_rate_pct < 30::numeric THEN '会员复购偏低'::text
            ELSE NULL::text
        END,
        CASE
            WHEN tiered.combined_platform_cost_rate_pct >= 40::numeric THEN '平台成本偏高'::text
            ELSE NULL::text
        END,
        CASE
            WHEN tiered.noodle_drink_attach_pct < 12::numeric THEN '饮品搭售偏低'::text
            ELSE NULL::text
        END) AS problem_combination
   FROM tiered;

-- ============================================================
-- Step 5: 验证
-- ============================================================
SELECT 'Materialized views created successfully' AS status;
