MATIH Platform is in active MVP development. Documentation reflects current implementation status.
21. Industry Examples & Walkthroughs
Manufacturing & Supply Chain
BI Lead Journey

BI Lead Journey: Plant Performance and OEE Analytics

Persona: Carlos Mendez, BI Lead at Apex Manufacturing Goal: Build the operations analytics platform for 4 plants with real-time OEE dashboards Primary Workbenches: BI Workbench, Data Workbench (Semantic Layer) Timeline: 10-week rollout across all 4 plants


Business Context

Apex Manufacturing operates 4 plants, each with its own SCADA system, production scheduling process, and reporting cadence. Plant managers currently assemble OEE numbers manually from three separate spreadsheets every Monday morning. The data is 3-5 days stale by the time it reaches the weekly operations review. When a machine goes down or a quality issue emerges, the response time is measured in hours -- not minutes.

Carlos Mendez's objective is to replace this fragmented reporting with a unified real-time analytics platform. Plant floor displays show live OEE. Shift supervisors get alerts on their phones. Plant managers see cross-line comparisons updated every 5 minutes. And the COO gets a single view of all 4 plants without asking anyone for a spreadsheet.


Stage 1: Ingestion

Connecting Data Sources

Carlos works with the data engineering team to connect all OEE-relevant data sources through the Ingestion Service:

Source connectivity matrix:

SourceSystemConnectorSync ModeFrequencyKey Data
Machine statusSCADA/Historian (OPC-UA)Airbyte custom connectorIncrementalEvery 5 minMachine state (running, idle, down, setup), alarm codes
Production ordersSAP ERP PostgreSQLAirbyte CDCIncrementalEvery 15 minPlanned vs actual quantities, cycle times, product specs
Quality resultsQMS PostgreSQLAirbyte CDCIncrementalEvery 15 minPass/fail counts, defect types, inspection timestamps
Energy metersSmart meters (Kafka)Kafka streamingContinuousEvery 1 minkWh per machine, demand kW, power factor
Shift schedulesHR system CSVFile ImportFull refreshWeeklyShift start/end, crew assignments, planned downtime
Supplier deliveriesSupplier portal CSVFile ImportFull refreshWeeklyDelivery dates, quantities, quality grades

SCADA ingestion configuration:

{
  "source": {
    "type": "opc_ua",
    "config": {
      "endpoints": [
        {"plant": "plant_1", "url": "opc.tcp://scada-p1.apex.internal:4840"},
        {"plant": "plant_2", "url": "opc.tcp://scada-p2.apex.internal:4840"},
        {"plant": "plant_3", "url": "opc.tcp://scada-p3.apex.internal:4840"},
        {"plant": "plant_4", "url": "opc.tcp://scada-p4.apex.internal:4840"}
      ],
      "node_patterns": [
        "ns=2;s=Machine.*.Status",
        "ns=2;s=Machine.*.CycleCount",
        "ns=2;s=Machine.*.AlarmCode"
      ],
      "polling_interval_ms": 5000
    }
  },
  "destination": {
    "type": "s3_parquet",
    "config": {
      "bucket": "apex-data-lake",
      "prefix": "raw/scada/",
      "partition_by": ["plant_id", "date"]
    }
  }
}

Stage 2: Discovery

Mapping the OEE Data Model

Carlos explores the catalog to understand how to compute OEE -- the gold standard manufacturing metric that combines three factors:

  OEE = Availability x Performance x Quality
  ════════════════════════════════════════════

  Availability = Run Time / Planned Production Time
  ┌──────────────────────────────────────────────────────┐
  │  Planned Production Time (shift hours - planned DT)  │
  │  ┌──────────────────────────────────────────┐        │
  │  │  Run Time (available - unplanned DT)     │        │
  │  └──────────────────────────────────────────┘        │
  └──────────────────────────────────────────────────────┘

  Performance = (Ideal Cycle Time x Total Pieces) / Run Time
  ┌──────────────────────────────────────────────────────┐
  │  Theoretical Max Output at ideal speed               │
  │  ┌──────────────────────────────────┐                │
  │  │  Actual Output (slower + stops)  │                │
  │  └──────────────────────────────────┘                │
  └──────────────────────────────────────────────────────┘

  Quality = Good Pieces / Total Pieces
  ┌──────────────────────────────────────────────────────┐
  │  Total Pieces Produced                               │
  │  ┌──────────────────────────────────────┐            │
  │  │  Good Pieces (passed inspection)     │            │
  │  └──────────────────────────────────────┘            │
  └──────────────────────────────────────────────────────┘

Discovering Status Code Inconsistencies

Data profiling reveals that machine status codes differ across plants -- the same physical state has different numeric codes:

-- Discover status code mappings per plant
SELECT
    plant_id,
    status_code,
    status_description,
    COUNT(*) AS occurrences
FROM machine_status_events
GROUP BY plant_id, status_code, status_description
ORDER BY plant_id, occurrences DESC
PlantCodeDescriptionStandardized State
Plant 11RunningRUNNING
Plant 12IdleIDLE
Plant 13Down - UnplannedDOWN_UNPLANNED
Plant 14SetupSETUP
Plant 15Planned MaintenanceDOWN_PLANNED
Plant 210Active ProductionRUNNING
Plant 220StandbyIDLE
Plant 230FaultDOWN_UNPLANNED
Plant 240ChangeoverSETUP
Plant 250Scheduled StopDOWN_PLANNED

Carlos creates a standardization mapping in the catalog and applies it as a transform in the ingestion pipeline so all downstream queries use consistent states.


Stage 3: Query

Defining Semantic Layer OEE Metrics

Carlos defines the OEE calculation as semantic layer metrics in the BI Workbench, ensuring every dashboard, report, and AI query uses the exact same formulas:

-- Semantic Layer: OEE metric definitions
-- These are registered as reusable metrics, not ad-hoc queries
 
-- METRIC: availability_rate
-- Dimensions: machine_id, line_id, plant_id, shift, date
SELECT
    machine_id,
    line_id,
    plant_id,
    shift_id,
    DATE_TRUNC('hour', event_timestamp) AS hour,
    -- Run time = total time in RUNNING state
    SUM(CASE WHEN standardized_state = 'RUNNING'
        THEN duration_minutes ELSE 0 END) AS run_time_minutes,
    -- Planned production time = shift duration - planned downtime
    SUM(CASE WHEN standardized_state NOT IN ('DOWN_PLANNED')
        THEN duration_minutes ELSE 0 END) AS planned_production_minutes,
    -- Availability = run time / planned production time
    ROUND(
        SUM(CASE WHEN standardized_state = 'RUNNING'
            THEN duration_minutes ELSE 0 END) * 100.0
        / NULLIF(SUM(CASE WHEN standardized_state NOT IN ('DOWN_PLANNED')
            THEN duration_minutes ELSE 0 END), 0),
        2
    ) AS availability_rate
FROM machine_status_standardized
GROUP BY machine_id, line_id, plant_id, shift_id,
         DATE_TRUNC('hour', event_timestamp)
-- METRIC: performance_rate
SELECT
    po.machine_id,
    e.line_id,
    e.plant_id,
    DATE_TRUNC('hour', po.end_time) AS hour,
    SUM(po.actual_qty) AS total_pieces,
    -- Ideal cycle time from product specs (seconds per piece)
    AVG(ps.ideal_cycle_time_seconds) AS ideal_cycle_time,
    -- Performance = (ideal cycle time * pieces) / run time
    ROUND(
        (AVG(ps.ideal_cycle_time_seconds) * SUM(po.actual_qty))
        / NULLIF(SUM(ms.run_time_seconds), 0) * 100.0,
        2
    ) AS performance_rate
FROM production_orders po
JOIN product_specs ps ON po.product_id = ps.product_id
JOIN equipment_registry e ON po.machine_id = e.machine_id
JOIN machine_run_time ms ON po.machine_id = ms.machine_id
    AND DATE_TRUNC('hour', po.end_time) = ms.hour
GROUP BY po.machine_id, e.line_id, e.plant_id,
         DATE_TRUNC('hour', po.end_time)
-- METRIC: quality_rate
SELECT
    qi.machine_id,
    e.line_id,
    e.plant_id,
    DATE_TRUNC('hour', qi.inspection_timestamp) AS hour,
    COUNT(*) AS total_inspected,
    SUM(CASE WHEN qi.pass_fail = 'PASS' THEN 1 ELSE 0 END) AS good_pieces,
    ROUND(
        SUM(CASE WHEN qi.pass_fail = 'PASS' THEN 1 ELSE 0 END) * 100.0
        / NULLIF(COUNT(*), 0),
        2
    ) AS quality_rate
FROM quality_inspections qi
JOIN equipment_registry e ON qi.machine_id = e.machine_id
GROUP BY qi.machine_id, e.line_id, e.plant_id,
         DATE_TRUNC('hour', qi.inspection_timestamp)
-- METRIC: composite_oee (combines all three)
SELECT
    a.machine_id,
    a.plant_id,
    a.hour,
    a.availability_rate,
    p.performance_rate,
    q.quality_rate,
    ROUND(
        (a.availability_rate / 100.0)
        * (p.performance_rate / 100.0)
        * (q.quality_rate / 100.0)
        * 100.0,
        2
    ) AS oee_percentage
FROM availability_metrics a
JOIN performance_metrics p ON a.machine_id = p.machine_id AND a.hour = p.hour
JOIN quality_metrics q ON a.machine_id = q.machine_id AND a.hour = q.hour

Validating Against Manual Reports

Carlos validates the semantic layer calculations against the manually computed plant reports from the previous quarter:

PlantPeriodManual OEEPlatform OEEDifferenceRoot Cause
Plant 1Q4 202574.2%72.8%-1.4%Manual excluded weekend maintenance from planned time
Plant 2Q4 202571.8%72.1%+0.3%Rounding differences in cycle time averaging
Plant 3Q4 202569.5%69.7%+0.2%Within acceptable tolerance
Plant 4Q4 202573.1%73.3%+0.2%Within acceptable tolerance

After resolving the Plant 1 discrepancy (aligning the definition of "planned production time" to exclude scheduled weekend maintenance), all plants match within 0.5%.


Stage 4: Orchestration

Real-Time OEE Pipeline

Carlos builds a multi-tier pipeline using the Pipeline Service:

  OEE Pipeline Architecture
  ═════════════════════════

  Tier 1: Real-time (every 5 minutes)
  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
  │ SCADA status │───▶│ Standardize  │───▶│ Compute live │
  │ events       │    │ status codes │    │ availability │
  └──────────────┘    └──────────────┘    └──────────────┘

  Tier 2: Near-real-time (hourly)
  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
  │ Production   │───▶│ Join with    │───▶│ Compute      │
  │ order data   │    │ cycle times  │    │ performance  │
  └──────────────┘    └──────────────┘    │ + quality    │
  ┌──────────────┐───▶│                   └──────────────┘
  │ Quality      │    │
  │ inspections  │    │
  └──────────────┘    │

  Tier 3: Aggregation (daily / shift-end)
  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
  │ Hourly OEE   │───▶│ Shift / day  │───▶│ Plant / line │
  │ by machine   │    │ rollups      │    │ summaries    │
  └──────────────┘    └──────────────┘    └──────────────┘

Pipeline configuration with quality gates:

{
  "workflow": "oee_pipeline",
  "tiers": [
    {
      "name": "realtime_availability",
      "schedule": "*/5 * * * *",
      "activities": [
        {
          "name": "ingest_machine_status",
          "type": "sql_transform",
          "config": {
            "query": "transforms/standardize_machine_status.sql",
            "output_table": "oee.machine_status_current"
          }
        },
        {
          "name": "compute_availability",
          "type": "sql_transform",
          "config": {
            "query": "transforms/availability_5min.sql",
            "output_table": "oee.availability_live"
          }
        }
      ]
    },
    {
      "name": "hourly_oee",
      "schedule": "5 * * * *",
      "activities": [
        {
          "name": "compute_performance",
          "type": "sql_transform",
          "config": {
            "query": "transforms/performance_hourly.sql",
            "output_table": "oee.performance_hourly"
          }
        },
        {
          "name": "compute_quality",
          "type": "sql_transform",
          "config": {
            "query": "transforms/quality_hourly.sql",
            "output_table": "oee.quality_hourly"
          }
        },
        {
          "name": "compute_composite_oee",
          "type": "sql_transform",
          "config": {
            "query": "transforms/composite_oee.sql",
            "output_table": "oee.oee_hourly"
          }
        },
        {
          "name": "validate_oee_completeness",
          "type": "data_quality",
          "config": {
            "expectations": [
              {"type": "expect_column_values_to_be_between", "column": "oee_percentage", "min": 0, "max": 100},
              {"type": "expect_column_values_to_be_between", "column": "availability_rate", "min": 0, "max": 100},
              {"type": "expect_column_values_to_not_be_null", "column": "machine_id"},
              {"type": "expect_table_row_count_to_be_between", "min": 180, "description": "At least 180 machines reporting per hour"}
            ]
          }
        }
      ]
    },
    {
      "name": "daily_summaries",
      "schedule": "0 0 * * *",
      "activities": [
        {
          "name": "shift_rollups",
          "type": "sql_transform",
          "config": {
            "query": "transforms/shift_day_rollups.sql",
            "output_table": "oee.oee_shift_daily"
          }
        },
        {
          "name": "plant_summaries",
          "type": "sql_transform",
          "config": {
            "query": "transforms/plant_summary.sql",
            "output_table": "oee.oee_plant_daily"
          }
        }
      ]
    }
  ]
}

Stage 5: Analysis

Benchmarking Against World-Class OEE

Carlos validates the computed OEE against industry benchmarks:

  OEE Benchmark Comparison (Apex Manufacturing)
  ══════════════════════════════════════════════

  World-Class:        ████████████████████████████████████████████  85%

  Apex Avg:           ████████████████████████████████████████      72.4%
  Plant 1:            ████████████████████████████████████████      74.2%
  Plant 2:            ██████████████████████████████████████        72.1%
  Plant 3:            ████████████████████████████████████          69.7%
  Plant 4:            ████████████████████████████████████████      73.3%

  Gap to World-Class: 12.6 percentage points

Bottleneck Machine Identification

-- Identify bottom 10 machines by OEE with root cause breakdown
SELECT
    m.machine_id,
    m.machine_type,
    e.plant_id,
    e.line_id,
    ROUND(AVG(m.oee_percentage), 1) AS avg_oee,
    ROUND(AVG(m.availability_rate), 1) AS avg_availability,
    ROUND(AVG(m.performance_rate), 1) AS avg_performance,
    ROUND(AVG(m.quality_rate), 1) AS avg_quality,
    -- Identify the weakest OEE component
    CASE
        WHEN AVG(m.availability_rate) <= LEAST(AVG(m.performance_rate), AVG(m.quality_rate))
            THEN 'AVAILABILITY'
        WHEN AVG(m.performance_rate) <= LEAST(AVG(m.availability_rate), AVG(m.quality_rate))
            THEN 'PERFORMANCE'
        ELSE 'QUALITY'
    END AS bottleneck_factor
FROM oee.oee_hourly m
JOIN equipment_registry e ON m.machine_id = e.machine_id
WHERE m.hour >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY m.machine_id, m.machine_type, e.plant_id, e.line_id
ORDER BY avg_oee ASC
LIMIT 10
MachineTypePlantOEEAvailabilityPerformanceQualityBottleneck
M-0142CNC LathePlant 348.2%62%88%88%AVAILABILITY
M-0087CNC MillPlant 253.1%71%82%91%PERFORMANCE
M-0211GrinderPlant 455.7%89%67%93%PERFORMANCE
M-0033CNC LathePlant 157.3%65%92%96%AVAILABILITY
M-0178EDMPlant 358.9%78%79%96%PERFORMANCE

Downtime Pareto Analysis

-- Pareto analysis of downtime reasons
SELECT
    downtime_reason,
    COUNT(*) AS event_count,
    SUM(duration_minutes) AS total_downtime_minutes,
    ROUND(SUM(duration_minutes) * 100.0
        / SUM(SUM(duration_minutes)) OVER (), 1) AS pct_of_total,
    SUM(SUM(duration_minutes)) OVER (ORDER BY SUM(duration_minutes) DESC)
        * 100.0 / SUM(SUM(duration_minutes)) OVER () AS cumulative_pct
FROM downtime_events
WHERE event_date >= CURRENT_DATE - INTERVAL '30 days'
  AND planned = false
GROUP BY downtime_reason
ORDER BY total_downtime_minutes DESC
  Downtime Pareto (Last 30 Days)
  ══════════════════════════════

  Tool breakage     ████████████████████████████  28%  ──── 28% (cumulative)
  Setup/changeover  ██████████████████████        22%  ──── 50%
  Bearing failure   ███████████████               15%  ──── 65%
  Material shortage ██████████                    10%  ──── 75%
  Software fault    ████████                       8%  ──── 83%
  Coolant issue     ██████                         6%  ──── 89%
  Operator error    █████                          5%  ──── 94%
  Other             ██████                         6%  ──── 100%

  Focus: Top 4 reasons account for 75% of all unplanned downtime

Stage 6: Productionization

Dashboard Suite

Carlos builds five interconnected dashboards in the BI Workbench:

Dashboard 1: Real-Time OEE (Plant Floor Display)

ComponentData SourceRefresh RatePurpose
Machine status grid (200 machines)oee.machine_status_current5 minAt-a-glance: green/yellow/red per machine
Plant OEE gaugeoee.availability_live + hourly metrics5 minCurrent shift OEE vs target (85%)
Active alarms listoee.machine_status_current5 minMachines currently down with reason
Shift production counterproduction_orders15 minParts produced vs plan for current shift

Dashboard 2: Downtime Pareto

ComponentData SourceRefresh RatePurpose
Pareto chart (top 10 reasons)downtime_eventsHourlyFocus improvement efforts on top causes
Downtime timeline (Gantt)downtime_eventsHourlyWhen and where downtime occurred
Machine downtime rankingoee.oee_hourlyHourlyWorst-performing machines this shift
MTBF/MTTR trendmaintenance_logsDailyReliability trend over 90 days

Dashboard 3: Quality Trend

ComponentData SourceRefresh RatePurpose
First-pass yield by linequality_inspectionsHourlyQuality rate trend by production line
Defect type breakdowndefect_annotationsHourlyWhich defects are most common
SPC control chartsquality_inspectionsHourlyStatistical process control for key dimensions
Scrap cost trackerproduction_orders + product_specsDailyDollar impact of quality failures

Dashboard 4: Energy Dashboard

ComponentData SourceRefresh RatePurpose
Real-time power draw by plantenergy_consumption1 minCurrent demand vs capacity
Energy per unit producedenergy_consumption + production_ordersHourlyEfficiency metric (kWh/part)
Idle energy wasteenergy_consumption + machine_statusHourlyEnergy consumed while machines are idle
Monthly energy cost trendenergy_consumptionDailyCost tracking vs budget

Dashboard 5: Supply Chain Status

ComponentData SourceRefresh RatePurpose
Supplier OTD scorecardsupplier_deliveriesWeeklyOn-time delivery rate by supplier
Material shortage alertsbill_of_materials + inventoryDailyParts at risk of stockout
Delivery timelinesupplier_deliveriesWeeklyUpcoming deliveries and delays
Supplier quality trendsupplier_deliveriesWeeklyIncoming material quality grades

Factory Floor Display Configuration

The Real-Time OEE dashboard is designed for large displays (55" monitors) mounted on the factory floor:

  ┌─────────────────────────────────────────────────────────────────┐
  │  APEX MANUFACTURING - PLANT 1        OEE: 74.2%    Shift: A    │
  │                                      Target: 85%   14:32       │
  ├──────────────────────┬──────────────────────────────────────────┤
  │ Machine Status Grid  │  Active Alarms                          │
  │ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┐ │  M-0033: DOWN - Tool breakage (47 min) │
  │ │G│G│Y│G│G│R│G│G│G│ │  M-0041: SETUP - Product changeover     │
  │ ├─┼─┼─┼─┼─┼─┼─┼─┼─┤ │  M-0055: DOWN - Coolant alarm (12 min) │
  │ │G│G│G│G│Y│G│G│G│G│ │                                          │
  │ ├─┼─┼─┼─┼─┼─┼─┼─┼─┤ │──────────────────────────────────────── │
  │ │G│G│G│R│G│G│G│Y│G│ │  Shift Production                       │
  │ ├─┼─┼─┼─┼─┼─┼─┼─┼─┤ │  Produced:  1,247 / 1,500 planned      │
  │ │G│G│G│G│G│G│G│G│G│ │  ████████████████████░░░░░  83%          │
  │ └─┘ └─┘ └─┘ └─┘ └─┘ │  On track: Yes (if no further downtime) │
  │ G=Running Y=Setup    │                                          │
  │ R=Down               │                                          │
  ├──────────────────────┴──────────────────────────────────────────┤
  │  OEE Components:  Avail: 88%  |  Perf: 91%  |  Quality: 93%   │
  └─────────────────────────────────────────────────────────────────┘

Stage 7: Feedback

Real-Time Alert Configuration

Carlos configures alerts that reach the right people at the right time:

{
  "alerts": [
    {
      "name": "oee_drop_critical",
      "condition": "plant_oee < 70% for current shift",
      "recipients": ["plant-manager", "shift-supervisor"],
      "channel": ["sms", "dashboard_flash"],
      "severity": "critical"
    },
    {
      "name": "unplanned_downtime_extended",
      "condition": "any machine DOWN_UNPLANNED > 30 minutes",
      "recipients": ["maintenance-lead", "shift-supervisor"],
      "channel": ["sms", "email"],
      "severity": "high"
    },
    {
      "name": "quality_rate_drop",
      "condition": "quality_rate < 95% for any line (rolling 1 hour)",
      "recipients": ["quality-engineer", "shift-supervisor"],
      "channel": ["email", "dashboard_highlight"],
      "severity": "high"
    },
    {
      "name": "energy_demand_peak",
      "condition": "plant_demand_kw > 90% of contracted capacity",
      "recipients": ["facilities-manager"],
      "channel": ["sms"],
      "severity": "high"
    },
    {
      "name": "supplier_delay_warning",
      "condition": "delivery > 2 days past promised date AND material inventory < 5 days supply",
      "recipients": ["procurement-manager", "production-planner"],
      "channel": ["email"],
      "severity": "medium"
    }
  ]
}

Weekly Plant Performance Digest

Carlos configures an automated weekly report delivered every Monday at 7 AM:

SectionContentRecipients
OEE SummaryPlant-level OEE with week-over-week trendAll plant managers, COO
Top 5 Downtime MachinesMachines with worst availability and root causesPlant managers, maintenance leads
Quality SummaryFirst-pass yield, scrap cost, top defect typesQuality managers
Energy ReportkWh per unit, total cost, waste during idleFacilities, COO
Supply Chain RisksLate deliveries, low-stock materialsProcurement, production planning

Stage 8: Experimentation

Shift-Level Gamification Dashboard

Carlos pilots a gamification experiment at Plant 1: a shift leaderboard showing which crew achieves the highest OEE, with friendly competition between shifts:

  Shift Leaderboard - Plant 1 (This Week)
  ═══════════════════════════════════════

  Rank  Shift    Crew Lead      OEE    vs Target  vs Last Week
  ──────────────────────────────────────────────────────────────
   1    Shift A  J. Martinez    78.3%    -6.7%       +2.1%
   2    Shift B  R. Kim         76.1%    -8.9%       +3.4%

  Best Machine OEE This Week: M-0012 (Lathe, Line A) - 91.2%
  Most Improved: M-0033 (Lathe, Line B) - 62.1% -> 71.8% (+9.7%)

Experiment results after 6 weeks:

MetricBefore GamificationAfter (6 weeks)Change
Plant 1 OEE74.2%78.4%+4.2pp
Shift-to-shift OEE variance8.3pp4.1pp-50%
Voluntary downtime reporting67% of events logged89% of events logged+22pp
Time to respond to alarms12 min average7 min average-42%

Energy Optimization Recommendations

Carlos partners with Lin Wei's data science team to add ML-driven energy insights:

-- Identify energy waste: machines consuming power while idle
SELECT
    e.machine_id,
    e.machine_type,
    e.plant_id,
    SUM(CASE WHEN ms.standardized_state = 'IDLE' THEN ec.kwh ELSE 0 END)
        AS idle_kwh_30d,
    SUM(ec.kwh) AS total_kwh_30d,
    ROUND(
        SUM(CASE WHEN ms.standardized_state = 'IDLE' THEN ec.kwh ELSE 0 END)
        * 100.0 / NULLIF(SUM(ec.kwh), 0),
        1
    ) AS idle_energy_pct,
    -- Estimated annual savings if idle power reduced by 50%
    ROUND(
        SUM(CASE WHEN ms.standardized_state = 'IDLE' THEN ec.kwh ELSE 0 END)
        * 12 * 0.5 * 0.12,  -- 12 months, 50% reduction, $0.12/kWh
        0
    ) AS estimated_annual_savings_usd
FROM energy_consumption ec
JOIN equipment_registry e ON ec.machine_id = e.machine_id
JOIN machine_status_standardized ms ON ec.machine_id = ms.machine_id
    AND ec.timestamp = ms.event_timestamp
WHERE ec.timestamp >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY e.machine_id, e.machine_type, e.plant_id
HAVING SUM(CASE WHEN ms.standardized_state = 'IDLE' THEN ec.kwh ELSE 0 END) > 100
ORDER BY idle_kwh_30d DESC
LIMIT 10

Overall Impact

After deploying the dashboard suite across all 4 plants:

MetricBefore DashboardsAfter (3 Months)Improvement
Avg OEE across all plants72.4%78.6%+6.2pp
Time to detect downtime15-45 min (shift report)< 5 min (real-time alert)-89%
Weekly reporting effort8 hours (manual assembly)0 hours (automated)-100%
Data staleness3-5 days< 5 minutes-99.9%
Energy waste (idle consumption)UnknownIdentified $180K/year savingsNew insight

Related Walkthroughs