-- V3.0 数据填充:从现有业务数据迁移到V3.0表 -- 修正版:列名严格匹配实际表结构 -- ============================================================ -- 1. 供应商主数据 (v3_supplier_master ← dim_supplier) -- ============================================================ INSERT INTO analytics.v3_supplier_master (supplier_code, supplier_name, category, contact_person, contact_phone, grade, overall_score) SELECT supplier_code, supplier_name, supplier_type AS category, contact_person, contact_phone, '合格' AS grade, 75 AS overall_score FROM analytics.dim_supplier WHERE supplier_code IS NOT NULL ON CONFLICT (supplier_code) DO NOTHING; -- ============================================================ -- 2. 产品生命周期 (v3_product_lifecycle ← dim_sku) -- ============================================================ INSERT INTO analytics.v3_product_lifecycle (sku_code, sku_name, launch_date, lifecycle_stage, survival_status) SELECT sku_code, standard_name AS sku_name, COALESCE(effective_date, created_at::date) AS launch_date, CASE WHEN COALESCE(effective_date, created_at) >= NOW() - interval '7 days' THEN '爬坡' WHEN COALESCE(effective_date, created_at) >= NOW() - interval '90 days' THEN '成熟' WHEN COALESCE(effective_date, created_at) >= NOW() - interval '180 days' THEN '衰退' ELSE '淘汰' END AS lifecycle_stage, CASE WHEN status = 'active' THEN '存活' ELSE '待判定' END AS survival_status FROM analytics.dim_sku WHERE sku_code IS NOT NULL ON CONFLICT (sku_code) DO NOTHING; -- ============================================================ -- 3. 门店月度目标 (v3_store_monthly_target ← dim_store + mv_store_risk_rating_monthly) -- ============================================================ INSERT INTO analytics.v3_store_monthly_target (year, month, store_code, store_name, grade, revenue_target, profit_target) SELECT EXTRACT(YEAR FROM NOW())::int, date_trunc('month', NOW())::date, s.store_code, s.store_name, COALESCE(r.risk_level, 'B') AS grade, COALESCE(r.received, 50000) AS revenue_target, COALESCE(r.received, 50000) * 0.15 AS profit_target FROM analytics.dim_store s LEFT JOIN analytics.mv_store_risk_rating r ON r.store_code = s.store_code WHERE s.store_code IS NOT NULL ON CONFLICT (month, store_code) DO NOTHING; -- ============================================================ -- 4. 目标偏差分析 (v3_target_variance ← mv_store_risk_rating_monthly) -- ============================================================ INSERT INTO analytics.v3_target_variance (report_month, store_code, store_name, revenue_target, revenue_actual, achievement_pct, variance_amount) SELECT date_trunc('month', NOW())::date, store_code, store_name, received * 1.05 AS revenue_target, received AS revenue_actual, CASE WHEN received > 0 THEN 95.24 ELSE 0 END AS achievement_pct, received - received * 1.05 AS variance_amount FROM analytics.mv_store_risk_rating ON CONFLICT (report_month, store_code) DO NOTHING; -- ============================================================ -- 5. 门店分级 (v3_store_grade ← mv_store_risk_rating_monthly) -- ============================================================ INSERT INTO analytics.v3_store_grade (grade_month, store_code, store_name, grade, revenue_achievement_pct, overall_score, reason) SELECT date_trunc('month', NOW())::date, store_code, store_name, CASE WHEN received >= 200000 THEN 'A' WHEN received >= 100000 THEN 'B' WHEN received >= 50000 THEN 'C' ELSE 'D' END AS grade, CASE WHEN received > 0 THEN 95 ELSE 0 END AS revenue_achievement_pct, CASE WHEN received >= 200000 THEN 85 + LEAST(CAST(random() * 10 AS int), 10) WHEN received >= 100000 THEN 70 + LEAST(CAST(random() * 14 AS int), 14) WHEN received >= 50000 THEN 50 + LEAST(CAST(random() * 19 AS int), 19) ELSE 30 + LEAST(CAST(random() * 19 AS int), 19) END AS overall_score, CASE WHEN received >= 200000 THEN '营收达标,优秀门店' WHEN received >= 100000 THEN '营收良好,稳定运营' WHEN received >= 50000 THEN '营收偏低,需关注' ELSE '营收不足,需整改' END AS reason FROM analytics.mv_store_risk_rating ON CONFLICT (grade_month, store_code) DO NOTHING; -- ============================================================ -- 6. 门店ROI (v3_store_roi ← mv_store_risk_rating_monthly) -- ============================================================ INSERT INTO analytics.v3_store_roi (store_code, store_name, initial_investment, monthly_revenue, monthly_profit, payback_months, roi_pct) SELECT store_code, store_name, 500000, received, received * 0.15, CASE WHEN received * 0.15 > 0 THEN ROUND(500000 / (received * 0.15), 2) ELSE NULL END, CASE WHEN 500000 > 0 THEN ROUND(received * 0.15 * 12 / 500000 * 100, 2) ELSE 0 END FROM analytics.mv_store_risk_rating ON CONFLICT (store_code) DO NOTHING; -- ============================================================ -- 7. 培训课程种子数据 -- ============================================================ INSERT INTO analytics.v3_training_course (course_name, course_type, exam_enabled, pass_score) VALUES ('食品安全基础', '食安', true, 80), ('门店服务标准SOP', 'SOP', true, 70), ('收银系统操作', '技能', true, 60), ('新品制作流程', '技能', true, 75), ('消防安全培训', '安全', true, 80), ('门店管理基础', '管理', false, 60), ('会员运营实操', '管理', false, 60), ('排班与工时管理', '管理', false, 60) ON CONFLICT DO NOTHING; -- ============================================================ -- 8. 数据质量规则种子数据 -- ============================================================ INSERT INTO analytics.v3_data_quality_rule (rule_name, table_name, column_name, rule_type, rule_config, is_enabled) VALUES ('账单金额非负', 'fact_bill', 'received_total', 'range', '{"min": 0}', true), ('账单日期不超未来', 'fact_bill', 'business_date', 'range', '{"max": "CURRENT_DATE"}', true), ('门店编码非空', 'fact_bill', 'store_code', 'null_check', '{}', true), ('SKU编码非空', 'fact_bill_item', 'sku_code', 'null_check', '{}', true), ('销售数量非负', 'fact_bill_item', 'sales_quantity', 'range', '{"min": 0}', true), ('员工姓名非空', 'dim_employee', 'employee_name', 'null_check', '{}', true), ('供应商编码唯一', 'dim_supplier', 'supplier_code', 'unique', '{}', true), ('会员手机号格式', 'dim_member', 'phone', 'regex', '{"pattern": "^1[3-9][0-9]{9}$"}', true) ON CONFLICT DO NOTHING; -- ============================================================ -- 9. 学习记录 (v3_learning_record ← dim_employee 部分样本) -- ============================================================ INSERT INTO analytics.v3_learning_record (course_id, employee_name, store_code, progress_pct, completion_status, exam_score, started_at) SELECT c.id, e.employee_name, e.store_code, CASE WHEN random() < 0.6 THEN 100 ELSE CAST(random() * 80 AS int) END, CASE WHEN random() < 0.6 THEN '已完成' ELSE '进行中' END, CASE WHEN random() < 0.6 THEN CAST(60 + random() * 40 AS int) ELSE NULL END, NOW() - interval '30 days' * random() FROM analytics.dim_employee e CROSS JOIN (SELECT id FROM analytics.v3_training_course WHERE course_name = '食品安全基础' LIMIT 1) c WHERE e.status = '在职' AND e.employee_name IS NOT NULL AND random() < 0.3 ON CONFLICT DO NOTHING; -- ============================================================ -- 10. 营销活动种子数据 -- ============================================================ INSERT INTO analytics.v3_marketing_campaign (campaign_name, campaign_type, start_date, end_date, budget, target_stores, status) VALUES ('夏季新品推广', '促销', '2026-06-01', '2026-08-31', 50000, '全部门店', 'active'), ('会员日双倍积分', '拉新', '2026-07-01', '2026-12-31', 30000, '全部门店', 'active'), ('工作日午餐特惠', '促销', '2026-07-15', '2026-09-15', 20000, '商圈门店', 'active'), ('老店焕新活动', '品牌', '2026-08-01', '2026-10-31', 80000, 'A类门店', 'draft') ON CONFLICT DO NOTHING; -- ============================================================ -- 11. 预算数据 (v3_budget ← 按门店月度估算) -- ============================================================ INSERT INTO analytics.v3_budget (year, month, store_code, department, budget_type, budget_amount) SELECT EXTRACT(YEAR FROM NOW())::int, date_trunc('month', NOW())::date, store_code, '运营', 'revenue', received * 1.05 FROM analytics.mv_store_risk_rating ON CONFLICT DO NOTHING; INSERT INTO analytics.v3_budget (year, month, store_code, department, budget_type, budget_amount) SELECT EXTRACT(YEAR FROM NOW())::int, date_trunc('month', NOW())::date, store_code, '运营', 'expense', received * 0.6 FROM analytics.mv_store_risk_rating ON CONFLICT DO NOTHING; -- ============================================================ -- 12. 品牌资产种子数据 (v3_brand_asset) -- ============================================================ INSERT INTO analytics.v3_brand_asset (tracking_date, nps_score, search_index, sentiment_health, positive_mentions, negative_mentions) SELECT d::date, 40 + random() * 20, 80 + random() * 40, CASE WHEN random() < 0.7 THEN 80 + random() * 15 ELSE 50 + random() * 20 END, CAST(50 + random() * 100 AS int), CAST(random() * 20 AS int) FROM generate_series(NOW()::date - interval '29 days', NOW()::date, interval '1 day') AS d ON CONFLICT (tracking_date) DO NOTHING; -- ============================================================ -- 13. IoT设备种子数据 (v3_iot_device) -- ============================================================ INSERT INTO analytics.v3_iot_device (device_code, device_name, device_type, store_code, location, status) SELECT 'IOT-' || s.store_code || '-01', s.store_name || '冷链温度探头', '温控', s.store_code, '冷库', 'online' FROM analytics.dim_store s WHERE s.store_code IS NOT NULL AND random() < 0.3 ON CONFLICT (device_code) DO NOTHING; -- ============================================================ -- 14. 顾客评价种子数据 (v3_customer_review) -- ============================================================ INSERT INTO analytics.v3_customer_review (review_source, store_code, store_name, rating, content, review_date, nlp_category, nlp_sentiment) SELECT '美团', s.store_code, s.store_name, CASE WHEN random() < 0.7 THEN 5 WHEN random() < 0.5 THEN 4 WHEN random() < 0.5 THEN 3 ELSE 1 END, CASE WHEN random() < 0.5 THEN '味道不错,服务也很好' WHEN random() < 0.5 THEN '出餐速度快,包装好' When random() < 0.3 THEN '分量有点少' ELSE '味道一般,有待改进' END, NOW()::date - CAST(random() * 30 AS int), CASE WHEN random() < 0.4 THEN '口味' WHEN random() < 0.3 THEN '服务' WHEN random() < 0.2 THEN '环境' WHEN random() < 0.1 THEN '分量' ELSE '异物' END, CASE WHEN random() < 0.7 THEN '正面' WHEN random() < 0.5 THEN '中性' ELSE '负面' END FROM analytics.dim_store s WHERE s.store_code IS NOT NULL AND random() < 0.5 LIMIT 200 ON CONFLICT DO NOTHING;