186 lines
8.5 KiB
Python
186 lines
8.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
创建指数算法相关表
|
|
"""
|
|
import sys
|
|
import os
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from config.settings import AppConfig
|
|
from database.connection import DatabaseConnection
|
|
from database.operations import DatabaseOperations
|
|
|
|
# 表DDL
|
|
DDL_STATEMENTS = [
|
|
# 参数配置表
|
|
"""
|
|
DROP TABLE IF EXISTS billiards_dws.cfg_index_parameters CASCADE;
|
|
CREATE TABLE billiards_dws.cfg_index_parameters (
|
|
param_id SERIAL PRIMARY KEY,
|
|
index_type VARCHAR(50) NOT NULL,
|
|
param_name VARCHAR(100) NOT NULL,
|
|
param_value NUMERIC(14,6) NOT NULL,
|
|
description TEXT,
|
|
effective_from DATE NOT NULL DEFAULT CURRENT_DATE,
|
|
effective_to DATE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT uk_cfg_index_parameters UNIQUE (index_type, param_name, effective_from)
|
|
);
|
|
CREATE INDEX idx_cfg_index_params_type ON billiards_dws.cfg_index_parameters (index_type);
|
|
""",
|
|
|
|
# 召回指数表
|
|
"""
|
|
DROP TABLE IF EXISTS billiards_dws.dws_member_recall_index CASCADE;
|
|
CREATE TABLE billiards_dws.dws_member_recall_index (
|
|
recall_id BIGSERIAL PRIMARY KEY,
|
|
site_id BIGINT NOT NULL,
|
|
tenant_id BIGINT NOT NULL,
|
|
member_id BIGINT NOT NULL,
|
|
days_since_last_visit INTEGER,
|
|
visit_interval_median NUMERIC(10,2),
|
|
visit_interval_mad NUMERIC(10,2),
|
|
days_since_first_visit INTEGER,
|
|
days_since_last_recharge INTEGER,
|
|
visits_last_14_days INTEGER NOT NULL DEFAULT 0,
|
|
visits_last_60_days INTEGER NOT NULL DEFAULT 0,
|
|
score_overdue NUMERIC(10,4),
|
|
score_new_bonus NUMERIC(10,4),
|
|
score_recharge_bonus NUMERIC(10,4),
|
|
score_hot_drop NUMERIC(10,4),
|
|
raw_score NUMERIC(14,6),
|
|
display_score NUMERIC(4,2),
|
|
calc_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
calc_version INTEGER NOT NULL DEFAULT 1,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT uk_dws_member_recall UNIQUE (site_id, member_id)
|
|
);
|
|
CREATE INDEX idx_dws_recall_display ON billiards_dws.dws_member_recall_index (site_id, display_score DESC);
|
|
""",
|
|
|
|
# 亲密指数表
|
|
"""
|
|
DROP TABLE IF EXISTS billiards_dws.dws_member_assistant_intimacy CASCADE;
|
|
CREATE TABLE billiards_dws.dws_member_assistant_intimacy (
|
|
intimacy_id BIGSERIAL PRIMARY KEY,
|
|
site_id BIGINT NOT NULL,
|
|
tenant_id BIGINT NOT NULL,
|
|
member_id BIGINT NOT NULL,
|
|
assistant_id BIGINT NOT NULL,
|
|
session_count INTEGER NOT NULL DEFAULT 0,
|
|
total_duration_minutes INTEGER NOT NULL DEFAULT 0,
|
|
basic_session_count INTEGER NOT NULL DEFAULT 0,
|
|
incentive_session_count INTEGER NOT NULL DEFAULT 0,
|
|
days_since_last_session INTEGER,
|
|
attributed_recharge_count INTEGER NOT NULL DEFAULT 0,
|
|
attributed_recharge_amount NUMERIC(14,2) NOT NULL DEFAULT 0,
|
|
score_frequency NUMERIC(10,4),
|
|
score_recency NUMERIC(10,4),
|
|
score_recharge NUMERIC(10,4),
|
|
score_duration NUMERIC(10,4),
|
|
burst_multiplier NUMERIC(6,4),
|
|
raw_score NUMERIC(14,6),
|
|
display_score NUMERIC(4,2),
|
|
calc_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
calc_version INTEGER NOT NULL DEFAULT 1,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT uk_dws_member_assistant_intimacy UNIQUE (site_id, member_id, assistant_id)
|
|
);
|
|
CREATE INDEX idx_dws_intimacy_member ON billiards_dws.dws_member_assistant_intimacy (site_id, member_id, display_score DESC);
|
|
CREATE INDEX idx_dws_intimacy_assistant ON billiards_dws.dws_member_assistant_intimacy (site_id, assistant_id, display_score DESC);
|
|
""",
|
|
|
|
# 分位点历史表
|
|
"""
|
|
DROP TABLE IF EXISTS billiards_dws.dws_index_percentile_history CASCADE;
|
|
CREATE TABLE billiards_dws.dws_index_percentile_history (
|
|
history_id BIGSERIAL PRIMARY KEY,
|
|
site_id BIGINT NOT NULL,
|
|
index_type VARCHAR(50) NOT NULL,
|
|
calc_time TIMESTAMPTZ NOT NULL,
|
|
percentile_5 NUMERIC(14,6),
|
|
percentile_95 NUMERIC(14,6),
|
|
percentile_5_smoothed NUMERIC(14,6),
|
|
percentile_95_smoothed NUMERIC(14,6),
|
|
record_count INTEGER,
|
|
min_raw_score NUMERIC(14,6),
|
|
max_raw_score NUMERIC(14,6),
|
|
avg_raw_score NUMERIC(14,6),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT uk_dws_index_percentile_history UNIQUE (site_id, index_type, calc_time)
|
|
);
|
|
CREATE INDEX idx_dws_percentile_history ON billiards_dws.dws_index_percentile_history (site_id, index_type, calc_time DESC);
|
|
"""
|
|
]
|
|
|
|
# 初始化参数
|
|
SEED_PARAMS = """
|
|
INSERT INTO billiards_dws.cfg_index_parameters
|
|
(index_type, param_name, param_value, description, effective_from)
|
|
VALUES
|
|
('RECALL', 'lookback_days', 60, '回溯窗口(天)', CURRENT_DATE),
|
|
('RECALL', 'sigma_min', 2.0, '波动下限(天)', CURRENT_DATE),
|
|
('RECALL', 'halflife_new', 7, '新客户半衰期(天)', CURRENT_DATE),
|
|
('RECALL', 'halflife_recharge', 10, '刚充值半衰期(天)', CURRENT_DATE),
|
|
('RECALL', 'weight_overdue', 3.0, '超期紧急性权重', CURRENT_DATE),
|
|
('RECALL', 'weight_new', 1.0, '新客户权重', CURRENT_DATE),
|
|
('RECALL', 'weight_recharge', 1.0, '刚充值权重', CURRENT_DATE),
|
|
('RECALL', 'weight_hot', 1.0, '热度断档权重', CURRENT_DATE),
|
|
('RECALL', 'percentile_lower', 5, '下锚分位数', CURRENT_DATE),
|
|
('RECALL', 'percentile_upper', 95, '上锚分位数', CURRENT_DATE),
|
|
('RECALL', 'ewma_alpha', 0.2, 'EWMA平滑系数', CURRENT_DATE),
|
|
('INTIMACY', 'lookback_days', 60, '回溯窗口(天)', CURRENT_DATE),
|
|
('INTIMACY', 'session_merge_hours', 4, '会话合并间隔(小时)', CURRENT_DATE),
|
|
('INTIMACY', 'recharge_attribute_hours', 1, '充值归因窗口(小时)', CURRENT_DATE),
|
|
('INTIMACY', 'amount_base', 500, '金额压缩基准(元)', CURRENT_DATE),
|
|
('INTIMACY', 'incentive_weight', 1.5, '附加课权重倍数', CURRENT_DATE),
|
|
('INTIMACY', 'halflife_session', 14, '会话衰减半衰期(天)', CURRENT_DATE),
|
|
('INTIMACY', 'halflife_last', 10, '最近一次半衰期(天)', CURRENT_DATE),
|
|
('INTIMACY', 'halflife_recharge', 21, '充值衰减半衰期(天)', CURRENT_DATE),
|
|
('INTIMACY', 'halflife_short', 7, '短期激增检测半衰期(天)', CURRENT_DATE),
|
|
('INTIMACY', 'halflife_long', 30, '长期激增检测半衰期(天)', CURRENT_DATE),
|
|
('INTIMACY', 'weight_frequency', 2.0, '频次权重', CURRENT_DATE),
|
|
('INTIMACY', 'weight_recency', 1.5, '最近一次权重', CURRENT_DATE),
|
|
('INTIMACY', 'weight_recharge', 2.0, '归因充值权重', CURRENT_DATE),
|
|
('INTIMACY', 'weight_duration', 0.5, '时长权重', CURRENT_DATE),
|
|
('INTIMACY', 'burst_gamma', 0.6, '激增放大系数', CURRENT_DATE),
|
|
('INTIMACY', 'percentile_lower', 5, '下锚分位数', CURRENT_DATE),
|
|
('INTIMACY', 'percentile_upper', 95, '上锚分位数', CURRENT_DATE),
|
|
('INTIMACY', 'ewma_alpha', 0.2, 'EWMA平滑系数', CURRENT_DATE)
|
|
ON CONFLICT (index_type, param_name, effective_from) DO NOTHING;
|
|
"""
|
|
|
|
def main():
|
|
print("创建指数算法相关表...")
|
|
|
|
config = AppConfig.load()
|
|
db_conn = DatabaseConnection(config.config["db"]["dsn"])
|
|
|
|
try:
|
|
with db_conn.conn.cursor() as cur:
|
|
# 创建表
|
|
for i, ddl in enumerate(DDL_STATEMENTS, 1):
|
|
print(f" 执行DDL {i}/{len(DDL_STATEMENTS)}...")
|
|
cur.execute(ddl)
|
|
|
|
# 初始化参数
|
|
print(" 初始化算法参数...")
|
|
cur.execute(SEED_PARAMS)
|
|
|
|
db_conn.conn.commit()
|
|
print("完成!")
|
|
|
|
# 验证
|
|
cur.execute("SELECT COUNT(*) FROM billiards_dws.cfg_index_parameters")
|
|
count = cur.fetchone()[0]
|
|
print(f" 已插入 {count} 个参数配置")
|
|
|
|
finally:
|
|
db_conn.close()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|