-- 迁移:为 dws_member_winback_index 和 dws_member_newconv_index 添加 visits_30d 字段 -- Fix-3:recall 维度需要 30 天到店次数,原先用 visits_14d 近似 -- 日期:2026-04-07 -- 重要:加列后必须重建所有引用这两张表的视图,否则视图看不到新列 -- 1. 加列 ALTER TABLE dws.dws_member_winback_index ADD COLUMN IF NOT EXISTS visits_30d integer DEFAULT 0 NOT NULL; ALTER TABLE dws.dws_member_newconv_index ADD COLUMN IF NOT EXISTS visits_30d integer DEFAULT 0 NOT NULL; -- 2. 重建 app schema RLS 视图(DROP + CREATE,因为列顺序变化导致 CREATE OR REPLACE 报错) DROP VIEW IF EXISTS app.v_dws_member_winback_index; CREATE VIEW app.v_dws_member_winback_index AS SELECT winback_id, site_id, tenant_id, member_id, status, segment, member_create_time, first_visit_time, last_visit_time, last_recharge_time, t_v, t_r, t_a, visits_14d, visits_30d, visits_60d, visits_total, spend_30d, spend_180d, sv_balance, recharge_60d_amt, interval_count, overdue_old, drop_old, recharge_old, value_old, raw_score, display_score, last_wechat_touch_time, calc_time, calc_version, created_at, updated_at, overdue_cdf_p, ideal_interval_days, ideal_next_visit_date FROM dws.dws_member_winback_index WHERE site_id = current_setting('app.current_site_id')::bigint; DROP VIEW IF EXISTS app.v_dws_member_newconv_index; CREATE VIEW app.v_dws_member_newconv_index AS SELECT newconv_id, site_id, tenant_id, member_id, status, segment, member_create_time, first_visit_time, last_visit_time, last_recharge_time, t_v, t_r, t_a, visits_14d, visits_30d, visits_60d, visits_total, spend_30d, spend_180d, sv_balance, recharge_60d_amt, interval_count, need_new, salvage_new, recharge_new, value_new, welcome_new, raw_score_welcome, raw_score_convert, raw_score, display_score_welcome, display_score_convert, display_score, last_wechat_touch_time, calc_time, calc_version, created_at, updated_at FROM dws.dws_member_newconv_index WHERE site_id = current_setting('app.current_site_id')::bigint; -- 3. 重建 dws.v_member_recall_priority (UNION ALL 视图) DROP VIEW IF EXISTS dws.v_member_recall_priority; CREATE VIEW dws.v_member_recall_priority AS SELECT site_id, tenant_id, member_id, 'WBI'::varchar(10) AS index_type, status, segment, member_create_time, first_visit_time, last_visit_time, last_recharge_time, t_v, t_r, t_a, visits_14d, visits_30d, visits_60d, visits_total, spend_30d, spend_180d, sv_balance, recharge_60d_amt, NULL::numeric(10,4) AS need_new, NULL::numeric(10,4) AS salvage_new, NULL::numeric(10,4) AS recharge_new, NULL::numeric(10,4) AS value_new, NULL::numeric(10,4) AS welcome_new, NULL::numeric(14,6) AS raw_score_welcome, NULL::numeric(14,6) AS raw_score_convert, raw_score, NULL::numeric(4,2) AS display_score_welcome, NULL::numeric(4,2) AS display_score_convert, display_score, last_wechat_touch_time, calc_time FROM dws.dws_member_winback_index UNION ALL SELECT site_id, tenant_id, member_id, 'NCI'::varchar(10) AS index_type, status, segment, member_create_time, first_visit_time, last_visit_time, last_recharge_time, t_v, t_r, t_a, visits_14d, visits_30d, visits_60d, visits_total, spend_30d, spend_180d, sv_balance, recharge_60d_amt, need_new, salvage_new, recharge_new, value_new, welcome_new, raw_score_welcome, raw_score_convert, raw_score, display_score_welcome, display_score_convert, display_score, last_wechat_touch_time, calc_time FROM dws.dws_member_newconv_index; -- 4. 回滚脚本(如需回滚,按逆序执行): -- DROP VIEW IF EXISTS dws.v_member_recall_priority; -- DROP VIEW IF EXISTS app.v_dws_member_newconv_index; -- DROP VIEW IF EXISTS app.v_dws_member_winback_index; -- ALTER TABLE dws.dws_member_winback_index DROP COLUMN IF EXISTS visits_30d; -- ALTER TABLE dws.dws_member_newconv_index DROP COLUMN IF EXISTS visits_30d; -- 然后重建原始视图(不含 visits_30d)