开发机迁移
This commit is contained in:
74
db/etl_feiqiu/migrations/20260407_add_visits_30d.sql
Normal file
74
db/etl_feiqiu/migrations/20260407_add_visits_30d.sql
Normal file
@@ -0,0 +1,74 @@
|
||||
-- 迁移:为 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)
|
||||
@@ -0,0 +1,58 @@
|
||||
-- 迁移:修复 app schema 快照视图多行膨胀
|
||||
-- 背景:consumption_summary 和 assistant_customer_stats 按 stat_date 存储每日快照,
|
||||
-- 原视图返回全部行导致 JOIN 行膨胀和前端卡片重复。
|
||||
-- 修复:DISTINCT ON 只取每个唯一键的最新 stat_date 行。
|
||||
-- 日期:2026-04-08
|
||||
|
||||
-- 1. v_dws_member_consumption_summary:每个 member_id 只取最新快照
|
||||
CREATE OR REPLACE VIEW app.v_dws_member_consumption_summary AS
|
||||
SELECT DISTINCT ON (member_id)
|
||||
id, site_id, tenant_id, member_id, stat_date,
|
||||
member_nickname, member_mobile, card_grade_name,
|
||||
register_date, first_consume_date, last_consume_date,
|
||||
total_visit_count, total_consume_amount, total_recharge_amount,
|
||||
total_table_fee, total_goods_amount, total_assistant_amount,
|
||||
visit_count_7d, visit_count_10d, visit_count_15d,
|
||||
visit_count_30d, visit_count_60d, visit_count_90d,
|
||||
consume_amount_7d, consume_amount_10d, consume_amount_15d,
|
||||
consume_amount_30d, consume_amount_60d, consume_amount_90d,
|
||||
cash_card_balance, gift_card_balance, total_card_balance,
|
||||
days_since_last, is_active_7d, is_active_30d, is_active_90d,
|
||||
customer_tier, created_at, updated_at,
|
||||
recharge_count_30d, recharge_count_60d, recharge_count_90d,
|
||||
recharge_amount_30d, recharge_amount_60d, recharge_amount_90d,
|
||||
avg_ticket_amount
|
||||
FROM dws.dws_member_consumption_summary
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
|
||||
ORDER BY member_id, stat_date DESC;
|
||||
|
||||
-- 2. v_dws_assistant_customer_stats:每对 (assistant_id, member_id) 只取最新快照
|
||||
CREATE OR REPLACE VIEW app.v_dws_assistant_customer_stats AS
|
||||
SELECT DISTINCT ON (assistant_id, member_id)
|
||||
id, site_id, tenant_id, assistant_id, assistant_nickname,
|
||||
member_id, member_nickname, member_mobile, stat_date,
|
||||
first_service_date, last_service_date,
|
||||
total_service_count, total_service_hours, total_service_amount,
|
||||
service_count_7d, service_count_10d, service_count_15d,
|
||||
service_count_30d, service_count_60d, service_count_90d,
|
||||
service_hours_7d, service_hours_10d, service_hours_15d,
|
||||
service_hours_30d, service_hours_60d, service_hours_90d,
|
||||
service_amount_7d, service_amount_10d, service_amount_15d,
|
||||
service_amount_30d, service_amount_60d, service_amount_90d,
|
||||
days_since_last, is_active_7d, is_active_30d,
|
||||
created_at, updated_at
|
||||
FROM dws.dws_assistant_customer_stats
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
|
||||
ORDER BY assistant_id, member_id, stat_date DESC;
|
||||
|
||||
-- 验证 SQL(执行后检查):
|
||||
-- SET app.current_site_id = '<site_id>';
|
||||
-- 1) SELECT COUNT(*), COUNT(DISTINCT member_id) FROM app.v_dws_member_consumption_summary; -- 两个值应该相等
|
||||
-- 2) SELECT COUNT(*), COUNT(DISTINCT (assistant_id, member_id)) FROM app.v_dws_assistant_customer_stats; -- 两个值应该相等
|
||||
-- 3) SELECT member_id, COUNT(*) FROM app.v_dws_member_consumption_summary GROUP BY member_id HAVING COUNT(*) > 1; -- 应返回 0 行
|
||||
|
||||
-- 回滚:
|
||||
-- CREATE OR REPLACE VIEW app.v_dws_member_consumption_summary AS
|
||||
-- SELECT ... FROM dws.dws_member_consumption_summary WHERE (site_id = ...); -- 去掉 DISTINCT ON 和 ORDER BY
|
||||
-- CREATE OR REPLACE VIEW app.v_dws_assistant_customer_stats AS
|
||||
-- SELECT ... FROM dws.dws_assistant_customer_stats WHERE (site_id = ...); -- 同上
|
||||
@@ -439,8 +439,10 @@ SELECT table_fee_log_id,
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
|
||||
;
|
||||
|
||||
-- CHANGE 2026-04-08 | DISTINCT ON 只取每对 (assistant, member) 最新快照
|
||||
CREATE OR REPLACE VIEW app.v_dws_assistant_customer_stats AS
|
||||
SELECT id,
|
||||
SELECT DISTINCT ON (assistant_id, member_id)
|
||||
id,
|
||||
site_id,
|
||||
tenant_id,
|
||||
assistant_id,
|
||||
@@ -478,7 +480,8 @@ SELECT id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM dws.dws_assistant_customer_stats
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
|
||||
ORDER BY assistant_id, member_id, stat_date DESC;
|
||||
;
|
||||
|
||||
CREATE OR REPLACE VIEW app.v_dws_assistant_daily_detail AS
|
||||
@@ -976,8 +979,10 @@ SELECT relation_id,
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
|
||||
;
|
||||
|
||||
-- CHANGE 2026-04-08 | DISTINCT ON 只取每个会员最新快照,避免多 stat_date 行膨胀
|
||||
CREATE OR REPLACE VIEW app.v_dws_member_consumption_summary AS
|
||||
SELECT id,
|
||||
SELECT DISTINCT ON (member_id)
|
||||
id,
|
||||
site_id,
|
||||
tenant_id,
|
||||
member_id,
|
||||
@@ -1024,7 +1029,8 @@ SELECT id,
|
||||
recharge_amount_90d,
|
||||
avg_ticket_amount
|
||||
FROM dws.dws_member_consumption_summary
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
|
||||
ORDER BY member_id, stat_date DESC;
|
||||
;
|
||||
|
||||
CREATE OR REPLACE VIEW app.v_dws_member_newconv_index AS
|
||||
@@ -1042,6 +1048,7 @@ SELECT newconv_id,
|
||||
t_r,
|
||||
t_a,
|
||||
visits_14d,
|
||||
visits_30d,
|
||||
visits_60d,
|
||||
visits_total,
|
||||
spend_30d,
|
||||
@@ -1167,6 +1174,7 @@ SELECT winback_id,
|
||||
t_r,
|
||||
t_a,
|
||||
visits_14d,
|
||||
visits_30d,
|
||||
visits_60d,
|
||||
visits_total,
|
||||
spend_30d,
|
||||
|
||||
@@ -789,6 +789,7 @@ CREATE TABLE dws.dws_member_newconv_index (
|
||||
t_r numeric(6,2),
|
||||
t_a numeric(6,2),
|
||||
visits_14d integer DEFAULT 0 NOT NULL,
|
||||
visits_30d integer DEFAULT 0 NOT NULL,
|
||||
visits_60d integer DEFAULT 0 NOT NULL,
|
||||
visits_total integer DEFAULT 0 NOT NULL,
|
||||
spend_30d numeric(14,2) DEFAULT 0 NOT NULL,
|
||||
@@ -907,6 +908,7 @@ CREATE TABLE dws.dws_member_winback_index (
|
||||
t_r numeric(6,2),
|
||||
t_a numeric(6,2),
|
||||
visits_14d integer DEFAULT 0 NOT NULL,
|
||||
visits_30d integer DEFAULT 0 NOT NULL,
|
||||
visits_60d integer DEFAULT 0 NOT NULL,
|
||||
visits_total integer DEFAULT 0 NOT NULL,
|
||||
spend_30d numeric(14,2) DEFAULT 0 NOT NULL,
|
||||
@@ -1297,6 +1299,7 @@ SELECT dws_member_winback_index.site_id,
|
||||
dws_member_winback_index.t_r,
|
||||
dws_member_winback_index.t_a,
|
||||
dws_member_winback_index.visits_14d,
|
||||
dws_member_winback_index.visits_30d,
|
||||
dws_member_winback_index.visits_60d,
|
||||
dws_member_winback_index.visits_total,
|
||||
dws_member_winback_index.spend_30d,
|
||||
@@ -1332,6 +1335,7 @@ UNION ALL
|
||||
dws_member_newconv_index.t_r,
|
||||
dws_member_newconv_index.t_a,
|
||||
dws_member_newconv_index.visits_14d,
|
||||
dws_member_newconv_index.visits_30d,
|
||||
dws_member_newconv_index.visits_60d,
|
||||
dws_member_newconv_index.visits_total,
|
||||
dws_member_newconv_index.spend_30d,
|
||||
|
||||
11
db/zqyy_app/migrations/20260407_add_completion_type.sql
Normal file
11
db/zqyy_app/migrations/20260407_add_completion_type.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
-- 迁移:coach_tasks 添加 completion_type 字段
|
||||
-- Fix-13:区分自动完成(auto)和手动完成(manual)
|
||||
-- 日期:2026-04-07
|
||||
|
||||
ALTER TABLE biz.coach_tasks
|
||||
ADD COLUMN IF NOT EXISTS completion_type character varying(10);
|
||||
|
||||
COMMENT ON COLUMN biz.coach_tasks.completion_type IS '完成类型:auto=系统自动检测到店, manual=助教手动标记';
|
||||
|
||||
-- 回滚:
|
||||
-- ALTER TABLE biz.coach_tasks DROP COLUMN IF EXISTS completion_type;
|
||||
@@ -16,6 +16,7 @@ CREATE SEQUENCE IF NOT EXISTS biz.cfg_task_generator_params_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.coach_task_history_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.coach_task_transfer_log_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.coach_tasks_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.recall_events_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.connectors_id_seq AS integer;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.dws_assistant_task_monthly_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.excel_upload_log_id_seq AS bigint;
|
||||
@@ -153,6 +154,7 @@ CREATE TABLE biz.coach_tasks (
|
||||
abandon_reason text,
|
||||
completed_at timestamp with time zone,
|
||||
completed_task_type character varying(50),
|
||||
completion_type character varying(10),
|
||||
parent_task_id bigint,
|
||||
created_at timestamp with time zone DEFAULT now(),
|
||||
updated_at timestamp with time zone DEFAULT now(),
|
||||
@@ -161,6 +163,17 @@ CREATE TABLE biz.coach_tasks (
|
||||
transferred_at timestamp with time zone
|
||||
);
|
||||
|
||||
CREATE TABLE biz.recall_events (
|
||||
id bigint DEFAULT nextval('biz.recall_events_id_seq'::regclass) NOT NULL,
|
||||
site_id bigint NOT NULL,
|
||||
assistant_id bigint NOT NULL,
|
||||
member_id bigint NOT NULL,
|
||||
pay_time timestamp with time zone NOT NULL,
|
||||
task_id bigint,
|
||||
task_type character varying(50),
|
||||
created_at timestamp with time zone DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE biz.connectors (
|
||||
id integer DEFAULT nextval('biz.connectors_id_seq'::regclass) NOT NULL,
|
||||
connector_key character varying(50) NOT NULL,
|
||||
@@ -341,6 +354,8 @@ ALTER TABLE biz.dws_assistant_task_monthly ADD CONSTRAINT dws_assistant_task_mon
|
||||
ALTER TABLE biz.excel_upload_log ADD CONSTRAINT excel_upload_log_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.notes ADD CONSTRAINT notes_task_id_fkey FOREIGN KEY (task_id) REFERENCES biz.coach_tasks(id);
|
||||
ALTER TABLE biz.notes ADD CONSTRAINT notes_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.recall_events ADD CONSTRAINT recall_events_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.recall_events ADD CONSTRAINT recall_events_task_id_fkey FOREIGN KEY (task_id) REFERENCES biz.coach_tasks(id);
|
||||
ALTER TABLE biz.salary_adjustments ADD CONSTRAINT salary_adjustments_upload_batch_id_fkey FOREIGN KEY (upload_batch_id) REFERENCES biz.excel_upload_log(id);
|
||||
ALTER TABLE biz.salary_adjustments ADD CONSTRAINT salary_adjustments_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.site_code_history ADD CONSTRAINT site_code_history_pkey PRIMARY KEY (id);
|
||||
@@ -386,5 +401,7 @@ CREATE INDEX idx_task_monthly_site_month ON biz.dws_assistant_task_monthly USING
|
||||
CREATE INDEX idx_excel_log_site ON biz.excel_upload_log USING btree (site_id, created_at DESC);
|
||||
CREATE INDEX idx_notes_target ON biz.notes USING btree (site_id, target_type, target_id);
|
||||
CREATE INDEX idx_salary_adj_assistant_month ON biz.salary_adjustments USING btree (assistant_id, salary_month);
|
||||
CREATE UNIQUE INDEX idx_recall_events_site_assistant_member_day ON biz.recall_events USING btree (site_id, assistant_id, member_id, (date_trunc('day', pay_time AT TIME ZONE 'Asia/Shanghai')));
|
||||
CREATE INDEX idx_recall_events_assistant_pay ON biz.recall_events USING btree (site_id, assistant_id, pay_time);
|
||||
CREATE INDEX idx_salary_adj_site_month ON biz.salary_adjustments USING btree (site_id, salary_month);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user