-- data-ana 模块 Mock 数据脚本 -- 用途:本地开发/集成测试时为 5 张宽表插入演示数据,验证查询逻辑 -- 使用方式(需先执行 clickhouse-init.sql): -- clickhouse-client --multiquery < scripts/data-ana-mock-data.sql -- -- 数据规模:2 班 × 10 学生 × 3 知识点 × 2 考试 = 120 行 student_dashboard_view -- 20 条错题 / 60 条掌握度快照 / 20 条考勤 / 10 条 AI 用量 -- 所有时间戳使用 now() - N days 模式,避免硬编码绝对日期导致脚本过期 USE edu_analytics; -- ===== 1. student_dashboard_view:学情宽表 ===== -- 班级 C001(高一 1 班)+ C002(高一 2 班),每班 10 学生 -- 2 次考试(EXAM001 数学月考 / EXAM002 数学期中),3 个数学知识点 INSERT INTO student_dashboard_view SELECT 'S' || toString(number + 1) AS student_id, -- S001..S020 IF(number < 10, 'C001', 'C002') AS class_id, -- 前 10 在 C001,后 10 在 C002 'EXAM001' AS exam_id, 'SUBJ_MATH' AS subject_id, 40 + (number % 60) AS score, -- 40-99 分 (number % 10) + 1 AS rank_in_class, -- 1-10 名 'KP_MATH_' || toString((number % 3) + 1) AS knowledge_point_id, -- KP_MATH_1/2/3 0.3 + ((number % 70) / 100.0) AS mastery_level, -- 0.30-0.99 (number % 5) AS error_count, -- 0-4 错题 now() - INTERVAL 7 DAY AS last_updated FROM numbers(20); -- 第二次考试(EXAM002),成绩略升 INSERT INTO student_dashboard_view SELECT 'S' || toString(number + 1) AS student_id, IF(number < 10, 'C001', 'C002') AS class_id, 'EXAM002' AS exam_id, 'SUBJ_MATH' AS subject_id, 50 + (number % 50) AS score, -- 50-99 分 (number % 10) + 1 AS rank_in_class, 'KP_MATH_' || toString((number % 3) + 1) AS knowledge_point_id, 0.4 + ((number % 60) / 100.0) AS mastery_level, (number % 4) AS error_count, now() - INTERVAL 1 DAY AS last_updated FROM numbers(20); -- ===== 2. student_errors:错题本 ===== INSERT INTO student_errors SELECT 'S' || toString((number % 20) + 1) AS student_id, 'Q_' || toString(number + 1) AS question_id, 'KP_MATH_' || toString((number % 3) + 1) AS knowledge_point_id, (number % 5) + 1 AS error_count, now() - INTERVAL (number % 30) DAY AS last_error_time, '错误类型:' || multiIf( number % 3 = 0, '计算失误', number % 3 = 1, '公式记忆错误', '审题不清' ) AS content FROM numbers(20); -- ===== 3. mastery_snapshot:掌握度历史快照(3 次计算,便于趋势查询) ===== INSERT INTO mastery_snapshot SELECT 'S' || toString((number % 20) + 1) AS student_id, 'KP_MATH_' || toString((number % 3) + 1) AS knowledge_point_id, 'SUBJ_MATH' AS subject_id, 0.3 + ((number % 70) / 100.0) AS mastery_level, now() - INTERVAL 30 DAY AS calculated_at, 'weighted_moving_avg' AS calculation_method FROM numbers(20); INSERT INTO mastery_snapshot SELECT 'S' || toString((number % 20) + 1) AS student_id, 'KP_MATH_' || toString((number % 3) + 1) AS knowledge_point_id, 'SUBJ_MATH' AS subject_id, 0.4 + ((number % 60) / 100.0) AS mastery_level, now() - INTERVAL 15 DAY AS calculated_at, 'weighted_moving_avg' AS calculation_method FROM numbers(20); INSERT INTO mastery_snapshot SELECT 'S' || toString((number % 20) + 1) AS student_id, 'KP_MATH_' || toString((number % 3) + 1) AS knowledge_point_id, 'SUBJ_MATH' AS subject_id, 0.5 + ((number % 50) / 100.0) AS mastery_level, now() AS calculated_at, 'weighted_moving_avg' AS calculation_method FROM numbers(20); -- ===== 4. attendance_logs:考勤记录(近 5 天,含缺勤/迟到) ===== INSERT INTO attendance_logs SELECT 'S' || toString((number % 20) + 1) AS student_id, IF(number % 20 < 10, 'C001', 'C002') AS class_id, today() - (number % 5) AS attendance_date, multiIf( number % 10 = 0, 'absent', -- 10% 缺勤 number % 5 = 0, 'late', -- 20% 迟到 'present' -- 其余正常 ) AS status, 'T001' AS recorded_by, multiIf(number % 10 = 0, '病假', '') AS remark, now() - INTERVAL (number % 5) DAY AS occurred_at FROM numbers(20); -- ===== 5. ai_usage_log:AI 用量计费(模拟 3 个 provider) ===== INSERT INTO ai_usage_log SELECT 'REQ_' || toString(number + 1) AS request_id, 'S' || toString((number % 20) + 1) AS user_id, arrayElement(['openai', 'anthropic', 'baichuan'], (number % 3) + 1) AS provider, arrayElement(['gpt-4o-mini', 'claude-3-haiku', 'baichuan2-turbo'], (number % 3) + 1) AS model, 100 + (number % 200) AS prompt_tokens, -- 100-299 50 + (number % 150) AS completion_tokens, -- 50-199 150 + (number % 350) AS total_tokens, -- 150-499 500 + (number % 2000) AS latency_ms, -- 500-2499 ms number % 5 != 0 AS success, -- 80% 成功 (number % 50) + 1 AS cost_cents, -- 1-50 分 now() - INTERVAL (number % 24) HOUR AS occurred_at FROM numbers(20); -- ===== 校验查询(可选执行) ===== SELECT 'student_dashboard_view' AS table_name, count() AS cnt FROM student_dashboard_view FINAL UNION ALL SELECT 'student_errors', count() FROM student_errors FINAL UNION ALL SELECT 'mastery_snapshot', count() FROM mastery_snapshot UNION ALL SELECT 'attendance_logs', count() FROM attendance_logs FINAL UNION ALL SELECT 'ai_usage_log', count() FROM ai_usage_log FINAL;