- 新增6个HTML可视化仪表盘组件用于数据展示 * 人效产值损耗三维模型仪表盘 * 指标趋势分析与拐点预警仪表盘 * 一页式决策简报仪表盘 * 订单延迟预警分析仪表盘 * 供应链风险预警仪表盘 * 工单执行进度与异常节点仪表盘 - 添加VSCode工作区配置文件 - 更新businessQueries.json业务查询配置 - 优化api_client.py API客户端实现 - 更新pyproject.toml项目依赖版本 - 重组SQL查询文件结构 - 删除v2版本冗余文档配置 - 添加v2版本技能清单文档 - 更新日志文件记录
427 lines
16 KiB
SQL
427 lines
16 KiB
SQL
-- =====================================================
|
||
-- 指标趋势分析与拐点预警SQL
|
||
-- Metric Trend Analysis and Turning Point Warning
|
||
-- 数据库: PostgreSQL
|
||
-- =====================================================
|
||
|
||
-- =====================================================
|
||
-- 1. 日度指标基础数据
|
||
-- =====================================================
|
||
WITH daily_metrics AS (
|
||
SELECT
|
||
DATE(lr.event_time_utc::timestamp) AS metric_date,
|
||
COUNT(DISTINCT lr.worker_name) AS worker_count,
|
||
SUM(lr.duration_minutes) / 60.0 AS total_hours,
|
||
SUM(lr.report_qty) AS total_output,
|
||
CASE WHEN SUM(lr.duration_minutes) > 0
|
||
THEN SUM(lr.report_qty) / (SUM(lr.duration_minutes) / 60.0)
|
||
ELSE 0 END AS hourly_efficiency
|
||
FROM fact_labor_report lr
|
||
GROUP BY DATE(lr.event_time_utc::timestamp)
|
||
),
|
||
|
||
daily_quality AS (
|
||
SELECT
|
||
DATE(qi.event_time_utc::timestamp) AS metric_date,
|
||
SUM(qi.pass_qty) AS pass_qty,
|
||
SUM(qi.fail_qty) AS fail_qty,
|
||
CASE WHEN SUM(qi.pass_qty) + SUM(qi.fail_qty) > 0
|
||
THEN SUM(qi.fail_qty) * 100.0 / (SUM(qi.pass_qty) + SUM(qi.fail_qty))
|
||
ELSE 0 END AS defect_rate
|
||
FROM fact_quality_inspection qi
|
||
GROUP BY DATE(qi.event_time_utc::timestamp)
|
||
),
|
||
|
||
daily_production AS (
|
||
SELECT
|
||
DATE(wo.event_time_utc::timestamp) AS metric_date,
|
||
SUM(wo.planned_qty) AS planned_qty,
|
||
SUM(wo.completed_qty) AS completed_qty,
|
||
CASE WHEN SUM(wo.planned_qty) > 0
|
||
THEN SUM(wo.completed_qty) * 100.0 / SUM(wo.planned_qty)
|
||
ELSE 0 END AS completion_rate
|
||
FROM fact_work_order wo
|
||
GROUP BY DATE(wo.event_time_utc::timestamp)
|
||
),
|
||
|
||
combined_daily AS (
|
||
SELECT
|
||
COALESCE(dm.metric_date, dq.metric_date, dp.metric_date) AS metric_date,
|
||
COALESCE(dm.worker_count, 0) AS worker_count,
|
||
COALESCE(dm.total_hours, 0) AS total_hours,
|
||
COALESCE(dm.total_output, 0) AS total_output,
|
||
COALESCE(dm.hourly_efficiency, 0) AS hourly_efficiency,
|
||
COALESCE(dq.defect_rate, 0) AS defect_rate,
|
||
COALESCE(dp.completion_rate, 0) AS completion_rate
|
||
FROM daily_metrics dm
|
||
FULL OUTER JOIN daily_quality dq ON dm.metric_date = dq.metric_date
|
||
FULL OUTER JOIN daily_production dp ON dm.metric_date = dp.metric_date
|
||
WHERE COALESCE(dm.metric_date, dq.metric_date, dp.metric_date) IS NOT NULL
|
||
),
|
||
|
||
numbered_data AS (
|
||
SELECT
|
||
*,
|
||
ROW_NUMBER() OVER (ORDER BY metric_date) AS day_seq
|
||
FROM combined_daily
|
||
),
|
||
|
||
-- =====================================================
|
||
-- 2. 移动平均计算 (7日移动平均)
|
||
-- =====================================================
|
||
moving_avg_step1 AS (
|
||
SELECT
|
||
metric_date,
|
||
day_seq,
|
||
worker_count,
|
||
total_output,
|
||
hourly_efficiency,
|
||
defect_rate,
|
||
completion_rate,
|
||
AVG(hourly_efficiency) OVER (ORDER BY metric_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma7_efficiency,
|
||
AVG(total_output) OVER (ORDER BY metric_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma7_output,
|
||
AVG(defect_rate) OVER (ORDER BY metric_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma7_defect_rate,
|
||
AVG(completion_rate) OVER (ORDER BY metric_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma7_completion_rate,
|
||
AVG(day_seq) OVER (ORDER BY metric_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_x
|
||
FROM numbered_data
|
||
),
|
||
|
||
moving_avg AS (
|
||
SELECT
|
||
*,
|
||
LAG(ma7_efficiency, 1) OVER (ORDER BY metric_date) AS prev_ma7_efficiency,
|
||
LAG(ma7_output, 1) OVER (ORDER BY metric_date) AS prev_ma7_output,
|
||
LAG(ma7_defect_rate, 1) OVER (ORDER BY metric_date) AS prev_ma7_defect_rate
|
||
FROM moving_avg_step1
|
||
),
|
||
|
||
-- =====================================================
|
||
-- 3. 简化的趋势斜率计算
|
||
-- =====================================================
|
||
slope_calc AS (
|
||
SELECT
|
||
*,
|
||
(ma7_efficiency - LAG(ma7_efficiency, 3) OVER (ORDER BY metric_date)) / 3.0 AS slope_efficiency,
|
||
(ma7_output - LAG(ma7_output, 3) OVER (ORDER BY metric_date)) / 3.0 AS slope_output,
|
||
(ma7_defect_rate - LAG(ma7_defect_rate, 3) OVER (ORDER BY metric_date)) / 3.0 AS slope_defect
|
||
FROM moving_avg
|
||
),
|
||
|
||
-- =====================================================
|
||
-- 4. 趋势判断与异常检测
|
||
-- =====================================================
|
||
trend_analysis AS (
|
||
SELECT
|
||
metric_date,
|
||
hourly_efficiency,
|
||
total_output,
|
||
defect_rate,
|
||
completion_rate,
|
||
ROUND(ma7_efficiency, 2) AS ma7_efficiency,
|
||
ROUND(ma7_output, 2) AS ma7_output,
|
||
ROUND(ma7_defect_rate, 2) AS ma7_defect_rate,
|
||
ROUND(COALESCE(slope_efficiency, 0), 4) AS slope_efficiency,
|
||
ROUND(COALESCE(slope_output, 0), 4) AS slope_output,
|
||
ROUND(COALESCE(slope_defect, 0), 4) AS slope_defect,
|
||
prev_ma7_efficiency,
|
||
prev_ma7_output,
|
||
prev_ma7_defect_rate,
|
||
|
||
CASE
|
||
WHEN COALESCE(slope_efficiency, 0) > 0.3 THEN 'RISING'
|
||
WHEN COALESCE(slope_efficiency, 0) < -0.3 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END AS efficiency_trend,
|
||
|
||
CASE
|
||
WHEN COALESCE(slope_output, 0) > 3 THEN 'RISING'
|
||
WHEN COALESCE(slope_output, 0) < -3 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END AS output_trend,
|
||
|
||
CASE
|
||
WHEN COALESCE(slope_defect, 0) > 0.3 THEN 'RISING'
|
||
WHEN COALESCE(slope_defect, 0) < -0.3 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END AS defect_trend,
|
||
|
||
CASE
|
||
WHEN ma7_efficiency > 0 AND ABS(hourly_efficiency - ma7_efficiency) > ma7_efficiency * 0.3 THEN 'ANOMALY'
|
||
ELSE 'NORMAL'
|
||
END AS efficiency_status,
|
||
|
||
CASE
|
||
WHEN ma7_output > 0 AND ABS(total_output - ma7_output) > ma7_output * 0.3 THEN 'ANOMALY'
|
||
ELSE 'NORMAL'
|
||
END AS output_status,
|
||
|
||
CASE
|
||
WHEN defect_rate > ma7_defect_rate * 1.5 AND defect_rate > 5 THEN 'ANOMALY'
|
||
ELSE 'NORMAL'
|
||
END AS defect_status
|
||
|
||
FROM slope_calc
|
||
)
|
||
|
||
-- =====================================================
|
||
-- 输出:日度趋势分析明细
|
||
-- =====================================================
|
||
SELECT
|
||
metric_date,
|
||
ROUND(hourly_efficiency, 2) AS hourly_output,
|
||
ma7_efficiency AS efficiency_ma7,
|
||
slope_efficiency,
|
||
efficiency_trend,
|
||
efficiency_status,
|
||
CASE
|
||
WHEN prev_ma7_efficiency IS NOT NULL
|
||
AND ma7_efficiency > prev_ma7_efficiency AND slope_efficiency < 0 THEN 'TURNING_POINT'
|
||
WHEN prev_ma7_efficiency IS NOT NULL
|
||
AND ma7_efficiency < prev_ma7_efficiency AND slope_efficiency > 0 THEN 'TURNING_POINT'
|
||
ELSE 'NONE'
|
||
END AS efficiency_turning_point,
|
||
ROUND(total_output, 0) AS daily_output,
|
||
ma7_output AS output_ma7,
|
||
slope_output,
|
||
output_trend,
|
||
output_status,
|
||
CASE
|
||
WHEN prev_ma7_output IS NOT NULL
|
||
AND ma7_output > prev_ma7_output AND slope_output < 0 THEN 'TURNING_POINT'
|
||
WHEN prev_ma7_output IS NOT NULL
|
||
AND ma7_output < prev_ma7_output AND slope_output > 0 THEN 'TURNING_POINT'
|
||
ELSE 'NONE'
|
||
END AS output_turning_point,
|
||
ROUND(defect_rate, 2) AS defect_rate,
|
||
ma7_defect_rate AS defect_rate_ma7,
|
||
slope_defect,
|
||
defect_trend,
|
||
defect_status,
|
||
CASE
|
||
WHEN prev_ma7_defect_rate IS NOT NULL
|
||
AND ma7_defect_rate > prev_ma7_defect_rate AND slope_defect < 0 THEN 'TURNING_POINT'
|
||
WHEN prev_ma7_defect_rate IS NOT NULL
|
||
AND ma7_defect_rate < prev_ma7_defect_rate AND slope_defect > 0 THEN 'TURNING_POINT'
|
||
ELSE 'NONE'
|
||
END AS defect_turning_point
|
||
FROM trend_analysis
|
||
ORDER BY metric_date DESC;
|
||
|
||
|
||
-- =====================================================
|
||
-- 补充查询1:周度趋势汇总
|
||
-- =====================================================
|
||
WITH weekly_metrics AS (
|
||
SELECT
|
||
DATE_TRUNC('week', lr.event_time_utc::timestamp)::date AS week_start,
|
||
COUNT(DISTINCT lr.worker_name) AS worker_count,
|
||
SUM(lr.duration_minutes) / 60.0 AS total_hours,
|
||
SUM(lr.report_qty) AS total_output,
|
||
CASE WHEN SUM(lr.duration_minutes) > 0
|
||
THEN SUM(lr.report_qty) / (SUM(lr.duration_minutes) / 60.0)
|
||
ELSE 0 END AS hourly_efficiency
|
||
FROM fact_labor_report lr
|
||
GROUP BY DATE_TRUNC('week', lr.event_time_utc::timestamp)
|
||
),
|
||
weekly_quality AS (
|
||
SELECT
|
||
DATE_TRUNC('week', qi.event_time_utc::timestamp)::date AS week_start,
|
||
SUM(qi.fail_qty) * 100.0 / NULLIF(SUM(qi.pass_qty) + SUM(qi.fail_qty), 0) AS defect_rate
|
||
FROM fact_quality_inspection qi
|
||
GROUP BY DATE_TRUNC('week', qi.event_time_utc::timestamp)
|
||
),
|
||
weekly_combined AS (
|
||
SELECT
|
||
wm.week_start,
|
||
wm.worker_count,
|
||
wm.total_hours,
|
||
wm.total_output,
|
||
wm.hourly_efficiency,
|
||
COALESCE(wq.defect_rate, 0) AS defect_rate
|
||
FROM weekly_metrics wm
|
||
LEFT JOIN weekly_quality wq ON wm.week_start = wq.week_start
|
||
),
|
||
weekly_with_lag AS (
|
||
SELECT
|
||
*,
|
||
LAG(hourly_efficiency, 1) OVER (ORDER BY week_start) AS prev_efficiency,
|
||
LAG(total_output, 1) OVER (ORDER BY week_start) AS prev_output,
|
||
LAG(defect_rate, 1) OVER (ORDER BY week_start) AS prev_defect_rate
|
||
FROM weekly_combined
|
||
)
|
||
SELECT
|
||
week_start,
|
||
worker_count,
|
||
ROUND(total_hours, 1) AS total_hours,
|
||
ROUND(total_output, 0) AS total_output,
|
||
ROUND(hourly_efficiency, 2) AS hourly_output,
|
||
ROUND(defect_rate, 2) AS defect_rate,
|
||
CASE
|
||
WHEN prev_efficiency IS NULL THEN 'NONE'
|
||
WHEN hourly_efficiency > prev_efficiency * 1.1 THEN 'RISING'
|
||
WHEN hourly_efficiency < prev_efficiency * 0.9 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END AS efficiency_trend,
|
||
CASE
|
||
WHEN prev_output IS NULL THEN 'NONE'
|
||
WHEN total_output > prev_output * 1.1 THEN 'RISING'
|
||
WHEN total_output < prev_output * 0.9 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END AS output_trend,
|
||
CASE
|
||
WHEN prev_defect_rate IS NULL THEN 'NONE'
|
||
WHEN defect_rate > prev_defect_rate * 1.2 THEN 'RISING'
|
||
WHEN defect_rate < prev_defect_rate * 0.8 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END AS defect_trend,
|
||
ROUND((hourly_efficiency - COALESCE(prev_efficiency, hourly_efficiency)) / NULLIF(prev_efficiency, 0) * 100, 1) AS efficiency_wow_pct
|
||
FROM weekly_with_lag
|
||
ORDER BY week_start DESC;
|
||
|
||
|
||
-- =====================================================
|
||
-- 补充查询2:指标趋势汇总报告
|
||
-- =====================================================
|
||
WITH
|
||
recent_data AS (
|
||
SELECT
|
||
DATE(lr.event_time_utc::timestamp) AS metric_date,
|
||
SUM(lr.report_qty) / NULLIF(SUM(lr.duration_minutes) / 60.0, 0) AS hourly_efficiency,
|
||
SUM(lr.report_qty) AS total_output
|
||
FROM fact_labor_report lr
|
||
WHERE lr.event_time_utc::timestamp >= CURRENT_DATE - INTERVAL '14 days'
|
||
GROUP BY DATE(lr.event_time_utc::timestamp)
|
||
),
|
||
recent_quality AS (
|
||
SELECT
|
||
DATE(qi.event_time_utc::timestamp) AS metric_date,
|
||
SUM(qi.fail_qty) * 100.0 / NULLIF(SUM(qi.pass_qty) + SUM(qi.fail_qty), 0) AS defect_rate
|
||
FROM fact_quality_inspection qi
|
||
WHERE qi.event_time_utc::timestamp >= CURRENT_DATE - INTERVAL '14 days'
|
||
GROUP BY DATE(qi.event_time_utc::timestamp)
|
||
),
|
||
period_stats AS (
|
||
SELECT
|
||
AVG(CASE WHEN rd.metric_date >= CURRENT_DATE - INTERVAL '7 days' THEN rd.hourly_efficiency END) AS avg_eff_7d,
|
||
AVG(CASE WHEN rd.metric_date >= CURRENT_DATE - INTERVAL '7 days' THEN rd.total_output END) AS avg_output_7d,
|
||
AVG(CASE WHEN rd.metric_date < CURRENT_DATE - INTERVAL '7 days' THEN rd.hourly_efficiency END) AS avg_eff_prev7d,
|
||
AVG(CASE WHEN rd.metric_date < CURRENT_DATE - INTERVAL '7 days' THEN rd.total_output END) AS avg_output_prev7d
|
||
FROM recent_data rd
|
||
),
|
||
quality_stats AS (
|
||
SELECT
|
||
AVG(CASE WHEN rq.metric_date >= CURRENT_DATE - INTERVAL '7 days' THEN rq.defect_rate END) AS avg_defect_7d,
|
||
AVG(CASE WHEN rq.metric_date < CURRENT_DATE - INTERVAL '7 days' THEN rq.defect_rate END) AS avg_defect_prev7d
|
||
FROM recent_quality rq
|
||
)
|
||
SELECT
|
||
'efficiency_per_hour' AS metric_name,
|
||
ROUND(ps.avg_eff_7d, 2) AS last_7d_avg,
|
||
ROUND(ps.avg_eff_prev7d, 2) AS prev_7d_avg,
|
||
ROUND((ps.avg_eff_7d - ps.avg_eff_prev7d) / NULLIF(ps.avg_eff_prev7d, 0) * 100, 1) AS change_rate_pct,
|
||
CASE
|
||
WHEN ps.avg_eff_7d > ps.avg_eff_prev7d * 1.05 THEN 'RISING'
|
||
WHEN ps.avg_eff_7d < ps.avg_eff_prev7d * 0.95 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END AS trend,
|
||
CASE
|
||
WHEN ABS(ps.avg_eff_7d - ps.avg_eff_prev7d) / NULLIF(ps.avg_eff_prev7d, 0) > 0.2 THEN 'ANOMALY'
|
||
ELSE 'NORMAL'
|
||
END AS warning
|
||
FROM period_stats ps
|
||
|
||
UNION ALL
|
||
|
||
SELECT
|
||
'daily_output',
|
||
ROUND(ps.avg_output_7d, 0),
|
||
ROUND(ps.avg_output_prev7d, 0),
|
||
ROUND((ps.avg_output_7d - ps.avg_output_prev7d) / NULLIF(ps.avg_output_prev7d, 0) * 100, 1),
|
||
CASE
|
||
WHEN ps.avg_output_7d > ps.avg_output_prev7d * 1.05 THEN 'RISING'
|
||
WHEN ps.avg_output_7d < ps.avg_output_prev7d * 0.95 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END,
|
||
CASE
|
||
WHEN ABS(ps.avg_output_7d - ps.avg_output_prev7d) / NULLIF(ps.avg_output_prev7d, 0) > 0.2 THEN 'ANOMALY'
|
||
ELSE 'NORMAL'
|
||
END
|
||
FROM period_stats ps
|
||
|
||
UNION ALL
|
||
|
||
SELECT
|
||
'defect_rate_pct',
|
||
ROUND(qs.avg_defect_7d, 2),
|
||
ROUND(qs.avg_defect_prev7d, 2),
|
||
ROUND((qs.avg_defect_7d - qs.avg_defect_prev7d) / NULLIF(qs.avg_defect_prev7d, 0) * 100, 1),
|
||
CASE
|
||
WHEN qs.avg_defect_7d > qs.avg_defect_prev7d * 1.1 THEN 'RISING'
|
||
WHEN qs.avg_defect_7d < qs.avg_defect_prev7d * 0.9 THEN 'FALLING'
|
||
ELSE 'STABLE'
|
||
END,
|
||
CASE
|
||
WHEN qs.avg_defect_7d > 8 THEN 'THRESHOLD_EXCEEDED'
|
||
WHEN qs.avg_defect_7d > qs.avg_defect_prev7d * 1.3 THEN 'ANOMALY_RISING'
|
||
ELSE 'NORMAL'
|
||
END
|
||
FROM quality_stats qs;
|
||
|
||
|
||
-- =====================================================
|
||
-- 补充查询3:拐点预警汇总
|
||
-- =====================================================
|
||
WITH daily_eff AS (
|
||
SELECT
|
||
DATE(lr.event_time_utc::timestamp) AS metric_date,
|
||
SUM(lr.report_qty) / NULLIF(SUM(lr.duration_minutes) / 60.0, 0) AS hourly_efficiency
|
||
FROM fact_labor_report lr
|
||
GROUP BY DATE(lr.event_time_utc::timestamp)
|
||
),
|
||
with_ma_step1 AS (
|
||
SELECT
|
||
metric_date,
|
||
hourly_efficiency,
|
||
AVG(hourly_efficiency) OVER (ORDER BY metric_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma7
|
||
FROM daily_eff
|
||
),
|
||
with_ma AS (
|
||
SELECT
|
||
metric_date,
|
||
hourly_efficiency,
|
||
ma7,
|
||
LAG(ma7, 1) OVER (ORDER BY metric_date) AS prev_ma7,
|
||
LAG(ma7, 2) OVER (ORDER BY metric_date) AS prev2_ma7
|
||
FROM with_ma_step1
|
||
),
|
||
turning_points AS (
|
||
SELECT
|
||
metric_date,
|
||
hourly_efficiency,
|
||
ma7,
|
||
prev_ma7,
|
||
prev2_ma7,
|
||
CASE
|
||
WHEN prev2_ma7 IS NOT NULL
|
||
AND prev_ma7 < prev2_ma7 AND ma7 > prev_ma7 THEN 'UPWARD'
|
||
WHEN prev2_ma7 IS NOT NULL
|
||
AND prev_ma7 > prev2_ma7 AND ma7 < prev_ma7 THEN 'DOWNWARD'
|
||
ELSE NULL
|
||
END AS turning_type
|
||
FROM with_ma
|
||
)
|
||
SELECT
|
||
metric_date,
|
||
ROUND(hourly_efficiency, 2) AS daily_efficiency,
|
||
ROUND(ma7, 2) AS ma7_line,
|
||
turning_type,
|
||
CASE
|
||
WHEN turning_type = 'UPWARD' THEN 'MAINTAIN_CURRENT_MEASURES'
|
||
WHEN turning_type = 'DOWNWARD' THEN 'INVESTIGATE_AND_IMPROVE'
|
||
ELSE 'NONE'
|
||
END AS recommendation
|
||
FROM turning_points
|
||
WHERE turning_type IS NOT NULL
|
||
ORDER BY metric_date DESC
|
||
LIMIT 10;
|