-- 订单延迟预警分析(最终优化版) -- Order Delay Warning Analysis WITH -- 1. 历史生产周期统计(全局平均,仅统计已完成工单) production_cycle_stats AS ( SELECT COALESCE( AVG( GREATEST(0, EXTRACT(DAY FROM last_updated_utc - event_time_utc)) ), 0 ) AS avg_production_days FROM fact_work_order WHERE status = 'CLOSED' AND last_updated_utc >= event_time_utc ), -- 2. 物流延误统计(按客户维度) logistics_delay_stats AS ( SELECT customer_id, AVG( GREATEST(0, EXTRACT(DAY FROM event_time_utc - doc_date_utc)) ) AS avg_logistics_delay_days, SUM( CASE WHEN EXTRACT(DAY FROM event_time_utc - doc_date_utc) > 3 THEN 1 ELSE 0 END ) AS delay_count FROM fact_sales_shipment WHERE doc_date_utc IS NOT NULL AND event_time_utc IS NOT NULL GROUP BY customer_id ), -- 3. 质量问题统计(全局平均) quality_issue_stats AS ( SELECT COALESCE( ROUND( SUM(fail_qty) * 100.0 / NULLIF(SUM(pass_qty + fail_qty), 0), 2 ), 0 ) AS defect_rate_pct FROM fact_quality_inspection WHERE pass_qty IS NOT NULL AND fail_qty IS NOT NULL ), -- 4. 报废率(全局) scrap_stats AS ( SELECT COALESCE( (SELECT COUNT(*) FROM fact_scrap) * 100.0 / NULLIF((SELECT COUNT(*) FROM fact_work_order WHERE status = 'CLOSED'), 0), 0 ) AS scrap_rate_pct ), -- 5. 当前生产滞后风险(全局) active_work_order_risk AS ( SELECT COUNT(*) AS active_wo_count, COALESCE( SUM( CASE WHEN planned_qty > 0 AND (completed_qty / planned_qty) < 0.3 AND EXTRACT(DAY FROM NOW() - event_time_utc) > 7 THEN 1 ELSE 0 END ), 0 ) AS lagging_wo_count FROM fact_work_order WHERE status IN ('OPEN', 'STARTED') ), -- 6. 合并全局指标为单行 global_metrics AS ( SELECT pcs.avg_production_days, qis.defect_rate_pct, ss.scrap_rate_pct, awr.active_wo_count, awr.lagging_wo_count FROM production_cycle_stats pcs, quality_issue_stats qis, scrap_stats ss, active_work_order_risk awr ) -- 主查询 SELECT so.sales_order_number AS order_number, c.customer_name AS customer_name, so.order_date_utc::DATE AS order_date, so.deal_amount AS order_amount, so.payment_status AS payment_status, -- 风险指标 ROUND(gm.avg_production_days::NUMERIC, 1) AS avg_production_days, ROUND(COALESCE(lds.avg_logistics_delay_days, 0)::NUMERIC, 1) AS avg_logistics_delay_days, COALESCE(lds.delay_count, 0)::INT AS historical_delay_count, ROUND(gm.defect_rate_pct::NUMERIC, 2) AS defect_rate_pct, ROUND(gm.scrap_rate_pct::NUMERIC, 2) AS scrap_rate_pct, gm.active_wo_count::INT AS active_work_order_count, gm.lagging_wo_count::INT AS lagging_work_order_count, -- 延迟概率计算 ROUND( LEAST(100, GREATEST(0, LEAST(25, GREATEST(0, gm.avg_production_days - 10) * 2.5) + LEAST(30, COALESCE(lds.avg_logistics_delay_days, 0) * 6) + LEAST(25, gm.defect_rate_pct * 2.5) + LEAST(20, gm.lagging_wo_count * 10) ))::NUMERIC, 1 ) AS delay_probability_pct, -- 预警等级 CASE WHEN ( LEAST(25, GREATEST(0, gm.avg_production_days - 10) * 2.5) + LEAST(30, COALESCE(lds.avg_logistics_delay_days, 0) * 6) + LEAST(25, gm.defect_rate_pct * 2.5) + LEAST(20, gm.lagging_wo_count * 10) ) >= 60 THEN 'RED' WHEN ( LEAST(25, GREATEST(0, gm.avg_production_days - 10) * 2.5) + LEAST(30, COALESCE(lds.avg_logistics_delay_days, 0) * 6) + LEAST(25, gm.defect_rate_pct * 2.5) + LEAST(20, gm.lagging_wo_count * 10) ) >= 30 THEN 'YELLOW' ELSE 'GREEN' END AS warning_level, -- 主要风险因素 CASE WHEN gm.lagging_wo_count >= 2 THEN 'PRODUCTION_SEVERELY_DELAYED' WHEN COALESCE(lds.avg_logistics_delay_days, 0) > 5 THEN 'HIGH_LOGISTICS_DELAY_RISK' WHEN gm.avg_production_days > 15 THEN 'LONG_PRODUCTION_CYCLE' WHEN gm.defect_rate_pct > 10 THEN 'QUALITY_ISSUES' ELSE 'NORMAL' END AS primary_risk_factor FROM fact_sales_order so LEFT JOIN dim_customer c ON so.customer_id = c.customer_id AND c.is_current = 't' CROSS JOIN global_metrics gm LEFT JOIN logistics_delay_stats lds ON so.customer_id = lds.customer_id ORDER BY delay_probability_pct DESC, so.order_date_utc DESC;