Files
K12Study/init/pg/recommendation/10_create_recommendation_tables.sql
2026-04-16 11:30:30 +08:00

441 lines
30 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

DROP SCHEMA IF EXISTS recommendation CASCADE;
CREATE SCHEMA IF NOT EXISTS recommendation;
DROP TABLE IF EXISTS recommendation.rc_recommendation_task CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_task (
task_id VARCHAR(64) PRIMARY KEY,
user_id VARCHAR(64) NOT NULL,
scene_code VARCHAR(32) NOT NULL,
trigger_source VARCHAR(32) NOT NULL DEFAULT 'SCHEDULE',
strategy_version VARCHAR(32),
profile_snapshot_json JSONB NOT NULL DEFAULT '{}'::JSONB,
status VARCHAR(16) NOT NULL DEFAULT 'CREATED',
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_rc_recommendation_task_status
CHECK (status IN ('CREATED', 'RUNNING', 'DONE', 'FAILED')),
CONSTRAINT chk_rc_recommendation_task_profile_json
CHECK (jsonb_typeof(profile_snapshot_json) = 'object'),
CONSTRAINT fk_rc_recommendation_task_user
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id)
);
COMMENT ON TABLE recommendation.rc_recommendation_task IS '推荐任务表';
COMMENT ON COLUMN recommendation.rc_recommendation_task.task_id IS '推荐任务ID';
COMMENT ON COLUMN recommendation.rc_recommendation_task.user_id IS '推荐目标用户ID';
COMMENT ON COLUMN recommendation.rc_recommendation_task.scene_code IS '推荐场景编码HOME/WRONGBOOK/REVIEW等';
COMMENT ON COLUMN recommendation.rc_recommendation_task.trigger_source IS '触发来源SCHEDULE/EVENT/MANUAL';
COMMENT ON COLUMN recommendation.rc_recommendation_task.strategy_version IS '推荐策略版本';
COMMENT ON COLUMN recommendation.rc_recommendation_task.profile_snapshot_json IS '画像快照JSON';
COMMENT ON COLUMN recommendation.rc_recommendation_task.status IS '任务状态';
COMMENT ON COLUMN recommendation.rc_recommendation_task.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_recommendation_task.created_at IS '创建时间';
COMMENT ON COLUMN recommendation.rc_recommendation_task.updated_at IS '更新时间';
DROP TABLE IF EXISTS recommendation.rc_recommendation_item CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_item (
item_id VARCHAR(64) PRIMARY KEY,
task_id VARCHAR(64) NOT NULL,
content_type VARCHAR(32) NOT NULL,
content_object_id VARCHAR(64) NOT NULL,
content_object_type VARCHAR(64) NOT NULL,
rank_no INTEGER NOT NULL,
score NUMERIC(10,6),
reason_codes VARCHAR(255),
metadata_json JSONB NOT NULL DEFAULT '{}'::JSONB,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_rc_recommendation_item_content_type
CHECK (content_type IN ('COURSE', 'QUESTION', 'PAPER', 'WRONG_QUESTION', 'REVIEW_PLAN', 'MIXED')),
CONSTRAINT chk_rc_recommendation_item_metadata_json
CHECK (jsonb_typeof(metadata_json) = 'object'),
CONSTRAINT uq_rc_recommendation_item_task_rank
UNIQUE (task_id, rank_no),
CONSTRAINT fk_rc_recommendation_item_task
FOREIGN KEY (task_id) REFERENCES recommendation.rc_recommendation_task(task_id) ON DELETE CASCADE
);
COMMENT ON TABLE recommendation.rc_recommendation_item IS '推荐结果明细表';
COMMENT ON COLUMN recommendation.rc_recommendation_item.item_id IS '推荐项ID';
COMMENT ON COLUMN recommendation.rc_recommendation_item.task_id IS '推荐任务ID';
COMMENT ON COLUMN recommendation.rc_recommendation_item.content_type IS '内容类型';
COMMENT ON COLUMN recommendation.rc_recommendation_item.content_object_id IS '内容对象ID';
COMMENT ON COLUMN recommendation.rc_recommendation_item.content_object_type IS '内容对象类型';
COMMENT ON COLUMN recommendation.rc_recommendation_item.rank_no IS '推荐位次';
COMMENT ON COLUMN recommendation.rc_recommendation_item.score IS '推荐分';
COMMENT ON COLUMN recommendation.rc_recommendation_item.reason_codes IS '推荐原因编码集合';
COMMENT ON COLUMN recommendation.rc_recommendation_item.metadata_json IS '扩展元数据JSON';
COMMENT ON COLUMN recommendation.rc_recommendation_item.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_recommendation_item.created_at IS '创建时间';
DROP TABLE IF EXISTS recommendation.rc_recommendation_feedback CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_feedback (
feedback_id VARCHAR(64) PRIMARY KEY,
item_id VARCHAR(64) NOT NULL,
user_id VARCHAR(64) NOT NULL,
event_type VARCHAR(16) NOT NULL,
event_value NUMERIC(10,4),
event_detail_json JSONB NOT NULL DEFAULT '{}'::JSONB,
event_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_rc_recommendation_feedback_event_type
CHECK (event_type IN ('EXPOSE', 'CLICK', 'START', 'COMPLETE', 'DISLIKE', 'SKIP')),
CONSTRAINT chk_rc_recommendation_feedback_detail_json
CHECK (jsonb_typeof(event_detail_json) = 'object'),
CONSTRAINT fk_rc_recommendation_feedback_item
FOREIGN KEY (item_id) REFERENCES recommendation.rc_recommendation_item(item_id) ON DELETE CASCADE,
CONSTRAINT fk_rc_recommendation_feedback_user
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id)
);
COMMENT ON TABLE recommendation.rc_recommendation_feedback IS '推荐反馈事件表';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.feedback_id IS '反馈事件ID';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.item_id IS '推荐项ID';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.user_id IS '用户ID';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_type IS '事件类型';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_value IS '事件值(可选)';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_detail_json IS '事件详情JSON';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_time IS '事件发生时间';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_recommendation_feedback.created_at IS '创建时间';
DROP TABLE IF EXISTS recommendation.rc_recommendation_effect_daily CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_effect_daily (
stat_date DATE NOT NULL,
scene_code VARCHAR(32) NOT NULL,
strategy_version VARCHAR(32) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
expose_count BIGINT NOT NULL DEFAULT 0,
click_count BIGINT NOT NULL DEFAULT 0,
complete_count BIGINT NOT NULL DEFAULT 0,
dislike_count BIGINT NOT NULL DEFAULT 0,
ctr NUMERIC(10,6) NOT NULL DEFAULT 0,
complete_rate NUMERIC(10,6) NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (stat_date, scene_code, strategy_version, tenant_id)
);
COMMENT ON TABLE recommendation.rc_recommendation_effect_daily IS '推荐效果日统计表';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.stat_date IS '统计日期';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.scene_code IS '推荐场景编码';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.strategy_version IS '策略版本';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.expose_count IS '曝光次数';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.click_count IS '点击次数';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.complete_count IS '完成次数';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.dislike_count IS '不喜欢次数';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.ctr IS '点击率';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.complete_rate IS '完成率';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.created_at IS '创建时间';
COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.updated_at IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_rc_recommendation_task_user_scene
ON recommendation.rc_recommendation_task(user_id, scene_code, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_rc_recommendation_task_tenant_status
ON recommendation.rc_recommendation_task(tenant_id, status, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_rc_recommendation_item_task
ON recommendation.rc_recommendation_item(task_id, rank_no);
CREATE INDEX IF NOT EXISTS idx_rc_recommendation_item_content
ON recommendation.rc_recommendation_item(content_object_type, content_object_id);
CREATE INDEX IF NOT EXISTS idx_rc_recommendation_feedback_item_event
ON recommendation.rc_recommendation_feedback(item_id, event_type, event_time DESC);
CREATE INDEX IF NOT EXISTS idx_rc_recommendation_feedback_user_event
ON recommendation.rc_recommendation_feedback(user_id, event_type, event_time DESC);
CREATE INDEX IF NOT EXISTS idx_rc_recommendation_effect_daily_tenant_date
ON recommendation.rc_recommendation_effect_daily(tenant_id, stat_date DESC);
DROP TABLE IF EXISTS recommendation.rc_student_profile_feature CASCADE;
DROP TABLE IF EXISTS recommendation.rc_student_profile_snapshot CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_student_profile_snapshot (
profile_id VARCHAR(64) PRIMARY KEY,
user_id VARCHAR(64) NOT NULL,
profile_version VARCHAR(32) NOT NULL,
profile_date DATE NOT NULL,
feature_source_version VARCHAR(64),
profile_json JSONB NOT NULL DEFAULT '{}'::JSONB,
confidence_score NUMERIC(6,4),
profile_status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_rc_student_profile_snapshot_user_version
UNIQUE (user_id, profile_version),
CONSTRAINT chk_rc_student_profile_snapshot_json
CHECK (jsonb_typeof(profile_json) = 'object'),
CONSTRAINT chk_rc_student_profile_snapshot_status
CHECK (profile_status IN ('ACTIVE', 'ARCHIVED')),
CONSTRAINT fk_rc_student_profile_snapshot_user
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id)
);
COMMENT ON TABLE recommendation.rc_student_profile_snapshot IS '学员画像快照表';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_id IS '画像ID';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.user_id IS '学员ID';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_version IS '画像版本';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_date IS '画像日期';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.feature_source_version IS '特征来源版本';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_json IS '画像JSON';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.confidence_score IS '画像置信度';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_status IS '画像状态';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.created_at IS '创建时间';
COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.updated_at IS '更新时间';
CREATE TABLE IF NOT EXISTS recommendation.rc_student_profile_feature (
feature_id VARCHAR(64) PRIMARY KEY,
profile_id VARCHAR(64) NOT NULL,
feature_group VARCHAR(32) NOT NULL,
feature_key VARCHAR(64) NOT NULL,
feature_value_num NUMERIC(18,6),
feature_value_text VARCHAR(512),
feature_value_json JSONB,
value_type VARCHAR(16) NOT NULL DEFAULT 'NUM',
source_domain VARCHAR(32) NOT NULL,
source_ref_id VARCHAR(64),
sample_time TIMESTAMP,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_rc_student_profile_feature_value_type
CHECK (value_type IN ('NUM', 'TEXT', 'JSON', 'BOOL')),
CONSTRAINT chk_rc_student_profile_feature_source_domain
CHECK (source_domain IN ('COURSE', 'HOMEWORK', 'GRADING', 'REVIEW', 'RECOMMENDATION', 'ACHIEVEMENT', 'SYSTEM')),
CONSTRAINT chk_rc_student_profile_feature_json
CHECK (feature_value_json IS NULL OR jsonb_typeof(feature_value_json) IN ('object', 'array', 'string', 'number', 'boolean')),
CONSTRAINT fk_rc_student_profile_feature_profile
FOREIGN KEY (profile_id) REFERENCES recommendation.rc_student_profile_snapshot(profile_id) ON DELETE CASCADE
);
COMMENT ON TABLE recommendation.rc_student_profile_feature IS '学员画像特征明细表';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_id IS '特征ID';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.profile_id IS '画像ID';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_group IS '特征组';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_key IS '特征键';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_value_num IS '数值特征值';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_value_text IS '文本特征值';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_value_json IS 'JSON特征值';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.value_type IS '值类型';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.source_domain IS '来源域';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.source_ref_id IS '来源对象ID';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.sample_time IS '采样时间';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_student_profile_feature.created_at IS '创建时间';
DROP TABLE IF EXISTS recommendation.rc_learning_loop_event CASCADE;
DROP TABLE IF EXISTS recommendation.rc_learning_loop_case CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_learning_loop_case (
loop_case_id VARCHAR(64) PRIMARY KEY,
user_id VARCHAR(64) NOT NULL,
wrong_question_id VARCHAR(64) NOT NULL,
review_plan_id VARCHAR(64),
profile_id VARCHAR(64),
recommendation_task_id VARCHAR(64),
recommendation_item_id VARCHAR(64),
feedback_id VARCHAR(64),
user_achievement_id VARCHAR(64),
loop_status VARCHAR(16) NOT NULL DEFAULT 'OPEN',
effect_score NUMERIC(10,4),
opened_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
closed_at TIMESTAMP,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_rc_learning_loop_case_status
CHECK (loop_status IN ('OPEN', 'IN_PROGRESS', 'CLOSED', 'FAILED')),
CONSTRAINT chk_rc_learning_loop_case_closed_at
CHECK (closed_at IS NULL OR closed_at >= opened_at),
CONSTRAINT fk_rc_learning_loop_case_user
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id),
CONSTRAINT fk_rc_learning_loop_case_wrong_question
FOREIGN KEY (wrong_question_id) REFERENCES question.gd_wrong_question(wrong_question_id),
CONSTRAINT fk_rc_learning_loop_case_review_plan
FOREIGN KEY (review_plan_id) REFERENCES question.gd_review_plan(review_plan_id),
CONSTRAINT fk_rc_learning_loop_case_profile
FOREIGN KEY (profile_id) REFERENCES recommendation.rc_student_profile_snapshot(profile_id),
CONSTRAINT fk_rc_learning_loop_case_recommendation_task
FOREIGN KEY (recommendation_task_id) REFERENCES recommendation.rc_recommendation_task(task_id),
CONSTRAINT fk_rc_learning_loop_case_recommendation_item
FOREIGN KEY (recommendation_item_id) REFERENCES recommendation.rc_recommendation_item(item_id),
CONSTRAINT fk_rc_learning_loop_case_feedback
FOREIGN KEY (feedback_id) REFERENCES recommendation.rc_recommendation_feedback(feedback_id),
CONSTRAINT fk_rc_learning_loop_case_user_achievement
FOREIGN KEY (user_achievement_id) REFERENCES achievement.ac_user_achievement(user_achievement_id)
);
COMMENT ON TABLE recommendation.rc_learning_loop_case IS '学习闭环主表(错题-复习-推荐-成就)';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.loop_case_id IS '闭环案例ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.user_id IS '用户ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.wrong_question_id IS '错题ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.review_plan_id IS '复习计划ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.profile_id IS '画像ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.recommendation_task_id IS '推荐任务ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.recommendation_item_id IS '推荐项ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.feedback_id IS '反馈事件ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.user_achievement_id IS '成就记录ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.loop_status IS '闭环状态';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.effect_score IS '闭环效果分';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.opened_at IS '闭环开启时间';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.closed_at IS '闭环关闭时间';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.created_at IS '创建时间';
COMMENT ON COLUMN recommendation.rc_learning_loop_case.updated_at IS '更新时间';
CREATE TABLE IF NOT EXISTS recommendation.rc_learning_loop_event (
loop_event_id VARCHAR(64) PRIMARY KEY,
loop_case_id VARCHAR(64) NOT NULL,
stage_code VARCHAR(32) NOT NULL,
stage_status VARCHAR(16) NOT NULL DEFAULT 'DONE',
event_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
event_score NUMERIC(10,4),
event_detail_json JSONB NOT NULL DEFAULT '{}'::JSONB,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_rc_learning_loop_event_stage_code
CHECK (stage_code IN ('WRONG_CAPTURED', 'REVIEW_PLANNED', 'PROFILE_UPDATED', 'RECOMMENDED', 'EXPOSED', 'ENGAGED', 'REVIEW_COMPLETED', 'ACHIEVED')),
CONSTRAINT chk_rc_learning_loop_event_stage_status
CHECK (stage_status IN ('PENDING', 'DONE', 'FAILED', 'SKIPPED')),
CONSTRAINT chk_rc_learning_loop_event_detail_json
CHECK (jsonb_typeof(event_detail_json) = 'object'),
CONSTRAINT fk_rc_learning_loop_event_case
FOREIGN KEY (loop_case_id) REFERENCES recommendation.rc_learning_loop_case(loop_case_id) ON DELETE CASCADE
);
COMMENT ON TABLE recommendation.rc_learning_loop_event IS '学习闭环阶段事件表';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.loop_event_id IS '闭环事件ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.loop_case_id IS '闭环案例ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.stage_code IS '阶段编码';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.stage_status IS '阶段状态';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.event_time IS '事件时间';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.event_score IS '阶段得分';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.event_detail_json IS '事件详情JSON';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_event.created_at IS '创建时间';
DROP TABLE IF EXISTS recommendation.rc_learning_loop_effect_daily CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_learning_loop_effect_daily (
stat_date DATE NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
opened_case_count BIGINT NOT NULL DEFAULT 0,
closed_case_count BIGINT NOT NULL DEFAULT 0,
achieved_case_count BIGINT NOT NULL DEFAULT 0,
avg_effect_score NUMERIC(10,4) NOT NULL DEFAULT 0,
avg_close_hours NUMERIC(10,4) NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (stat_date, tenant_id)
);
COMMENT ON TABLE recommendation.rc_learning_loop_effect_daily IS '学习闭环效果日统计表';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.stat_date IS '统计日期';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.opened_case_count IS '开启案例数';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.closed_case_count IS '关闭案例数';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.achieved_case_count IS '达成成就案例数';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.avg_effect_score IS '平均效果分';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.avg_close_hours IS '平均闭环时长(小时)';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.created_at IS '创建时间';
COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.updated_at IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_rc_student_profile_snapshot_user_date
ON recommendation.rc_student_profile_snapshot(user_id, profile_date DESC);
CREATE INDEX IF NOT EXISTS idx_rc_student_profile_snapshot_tenant_version
ON recommendation.rc_student_profile_snapshot(tenant_id, profile_version, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_rc_student_profile_feature_profile_group
ON recommendation.rc_student_profile_feature(profile_id, feature_group, feature_key);
CREATE INDEX IF NOT EXISTS idx_rc_student_profile_feature_source
ON recommendation.rc_student_profile_feature(source_domain, source_ref_id);
CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_case_user_status
ON recommendation.rc_learning_loop_case(user_id, loop_status, opened_at DESC);
CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_case_wrong_question
ON recommendation.rc_learning_loop_case(wrong_question_id, opened_at DESC);
CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_case_tenant_status
ON recommendation.rc_learning_loop_case(tenant_id, loop_status, opened_at DESC);
CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_event_case_stage_time
ON recommendation.rc_learning_loop_event(loop_case_id, stage_code, event_time DESC);
CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_event_tenant_time
ON recommendation.rc_learning_loop_event(tenant_id, event_time DESC);
CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_effect_daily_tenant_date
ON recommendation.rc_learning_loop_effect_daily(tenant_id, stat_date DESC);
DROP TABLE IF EXISTS recommendation.rc_loop_metric_map CASCADE;
DROP TABLE IF EXISTS recommendation.rc_loop_stage_achievement_map CASCADE;
CREATE TABLE IF NOT EXISTS recommendation.rc_loop_stage_achievement_map (
stage_map_id VARCHAR(64) PRIMARY KEY,
stage_code VARCHAR(32) NOT NULL,
event_code VARCHAR(64) NOT NULL,
template_id VARCHAR(64),
metric_id VARCHAR(64),
award_source VARCHAR(32) NOT NULL DEFAULT 'RULE_ENGINE',
priority INTEGER NOT NULL DEFAULT 100,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
ext_json JSONB NOT NULL DEFAULT '{}'::JSONB,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_rc_loop_stage_achievement_map
UNIQUE (tenant_id, stage_code, event_code, priority),
CONSTRAINT chk_rc_loop_stage_achievement_map_stage_code
CHECK (stage_code IN ('WRONG_CAPTURED', 'REVIEW_PLANNED', 'PROFILE_UPDATED', 'RECOMMENDED', 'EXPOSED', 'ENGAGED', 'REVIEW_COMPLETED', 'ACHIEVED')),
CONSTRAINT chk_rc_loop_stage_achievement_map_award_source
CHECK (award_source IN ('RULE_ENGINE', 'MANUAL', 'SYSTEM')),
CONSTRAINT chk_rc_loop_stage_achievement_map_ext_json
CHECK (jsonb_typeof(ext_json) = 'object'),
CONSTRAINT fk_rc_loop_stage_achievement_map_event
FOREIGN KEY (event_code) REFERENCES achievement.ac_achievement_event_dict(event_code),
CONSTRAINT fk_rc_loop_stage_achievement_map_template
FOREIGN KEY (template_id) REFERENCES achievement.ac_achievement_rule_template(template_id),
CONSTRAINT fk_rc_loop_stage_achievement_map_metric
FOREIGN KEY (metric_id) REFERENCES achievement.ac_achievement_metric_def(metric_id)
);
COMMENT ON TABLE recommendation.rc_loop_stage_achievement_map IS '闭环阶段到成就事件映射表(通用配置)';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.stage_map_id IS '阶段映射ID';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.stage_code IS '闭环阶段编码';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.event_code IS '成就事件编码';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.template_id IS '成就规则模板ID';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.metric_id IS '成就指标ID';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.award_source IS '发放来源';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.priority IS '优先级';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.enabled IS '是否启用';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.ext_json IS '扩展配置JSON';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.created_at IS '创建时间';
COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.updated_at IS '更新时间';
CREATE TABLE IF NOT EXISTS recommendation.rc_loop_metric_map (
metric_map_id VARCHAR(64) PRIMARY KEY,
stage_code VARCHAR(32) NOT NULL,
metric_id VARCHAR(64) NOT NULL,
source_field VARCHAR(64) NOT NULL,
agg_method VARCHAR(16) NOT NULL DEFAULT 'LATEST',
weight NUMERIC(6,4) NOT NULL DEFAULT 1.0000,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
ext_json JSONB NOT NULL DEFAULT '{}'::JSONB,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_rc_loop_metric_map
UNIQUE (tenant_id, stage_code, metric_id, source_field),
CONSTRAINT chk_rc_loop_metric_map_stage_code
CHECK (stage_code IN ('WRONG_CAPTURED', 'REVIEW_PLANNED', 'PROFILE_UPDATED', 'RECOMMENDED', 'EXPOSED', 'ENGAGED', 'REVIEW_COMPLETED', 'ACHIEVED')),
CONSTRAINT chk_rc_loop_metric_map_agg_method
CHECK (agg_method IN ('LATEST', 'SUM', 'AVG', 'MAX', 'MIN', 'COUNT')),
CONSTRAINT chk_rc_loop_metric_map_weight
CHECK (weight > 0 AND weight <= 1),
CONSTRAINT chk_rc_loop_metric_map_ext_json
CHECK (jsonb_typeof(ext_json) = 'object'),
CONSTRAINT fk_rc_loop_metric_map_metric
FOREIGN KEY (metric_id) REFERENCES achievement.ac_achievement_metric_def(metric_id)
);
COMMENT ON TABLE recommendation.rc_loop_metric_map IS '闭环指标映射表(通用配置)';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.metric_map_id IS '指标映射ID';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.stage_code IS '闭环阶段编码';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.metric_id IS '成就指标ID';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.source_field IS '来源字段名';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.agg_method IS '聚合方法';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.weight IS '权重';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.enabled IS '是否启用';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.ext_json IS '扩展配置JSON';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.tenant_id IS '租户ID';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.created_at IS '创建时间';
COMMENT ON COLUMN recommendation.rc_loop_metric_map.updated_at IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_rc_loop_stage_achievement_map_tenant_stage
ON recommendation.rc_loop_stage_achievement_map(tenant_id, stage_code, enabled, priority);
CREATE INDEX IF NOT EXISTS idx_rc_loop_stage_achievement_map_event
ON recommendation.rc_loop_stage_achievement_map(event_code, tenant_id, enabled);
CREATE INDEX IF NOT EXISTS idx_rc_loop_metric_map_tenant_stage
ON recommendation.rc_loop_metric_map(tenant_id, stage_code, enabled);