Try CrateDB Live: More Queries
- 1. Choose Scenario
- 2. Get Ready
- 3. Run CrateDB
- 4. Import Data
- 5. Explore Queries
- 6. More Queries
- 7. Connect
- 8. Next Steps
B. Analytical Patterns
B1. CTE: Detect Devices With Rising Metric Values
Compare each device's average reading across two consecutive 6-hour windows. Flags devices where the recent window is >10% higher than the prior window, which is the early-drift signature used in predictive maintenance workflows.
SELECT
device_id,
device_type,
plant_id,
ROUND(avg_prior, 2) AS avg_prior_6h,
ROUND(avg_recent, 2) AS avg_recent_6h,
ROUND(avg_recent - avg_prior, 2) AS absolute_delta,
ROUND(
(avg_recent - avg_prior) / NULLIF(avg_prior, 0) * 100,
1
) AS pct_change
FROM
(
SELECT
tags['device_id'] AS device_id,
tags['device_type'] AS device_type,
tags['plant_id'] AS plant_id,
AVG(
CASE WHEN "timestamp" >= TIMESTAMP '2025-09-07 06:00:00'
AND "timestamp" < TIMESTAMP '2025-09-07 12:00:00' THEN fields['metric_value'] END
) AS avg_recent,
AVG(
CASE WHEN "timestamp" >= TIMESTAMP '2025-09-07 00:00:00'
AND "timestamp" < TIMESTAMP '2025-09-07 06:00:00' THEN fields['metric_value'] END
) AS avg_prior
FROM
rtia.iot_data
WHERE
"timestamp" >= TIMESTAMP '2025-09-07 00:00:00'
AND "timestamp" < TIMESTAMP '2025-09-07 12:00:00'
GROUP BY
tags['device_id'],
tags['device_type'],
tags['plant_id']
) windows
WHERE
avg_prior IS NOT NULL
AND (avg_recent - avg_prior) / NULLIF(avg_prior, 0) > 0.10
ORDER BY
pct_change DESC
LIMIT
20;
| device_id | device_type | plant_id | avg_prior_6h | avg_recent_6h | absolute_delta | pct_change |
|-------------|--------------------|-----------------|--------------|---------------|----------------|------------|
| DEVICE_0028 | flow_meter | PLANT_HAMBURG | 119.11 | 159.54 | 40.43 | 33.9 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | 0.98 | 1.27 | 0.29 | 29.8 |
| DEVICE_0081 | vibration_sensor | PLANT_STUTTGART | 2.47 | 3.18 | 0.71 | 28.6 |
| DEVICE_0068 | power_meter | PLANT_HAMBURG | 167.81 | 211.99 | 44.18 | 26.3 |
| DEVICE_0039 | temperature_sensor | PLANT_DORTMUND | 47.6 | 59.21 | 11.61 | 24.4 |
| DEVICE_0074 | pressure_sensor | PLANT_DORTMUND | 3.08 | 3.78 | 0.7 | 22.7 |
| DEVICE_0015 | temperature_sensor | PLANT_LEIPZIG | 54.27 | 65.53 | 11.26 | 20.7 |
| DEVICE_0082 | temperature_sensor | PLANT_MUNICH | 47.14 | 56.18 | 9.05 | 19.2 |
| DEVICE_0077 | vibration_sensor | PLANT_MUNICH | 1.26 | 1.49 | 0.23 | 18.2 |
| DEVICE_0083 | power_meter | PLANT_HAMBURG | 281.63 | 325.06 | 43.43 | 15.4 |
B2. Sustained Fault Detection With Having
Find devices that breached warning threshold at least 10 times in a single day, distinguishing sustained degradation from transient noise spikes.
SELECT
device_id,
device_type,
plant_id,
ROUND(avg_prior, 2) AS avg_prior_6h,
ROUND(avg_recent, 2) AS avg_recent_6h,
ROUND(avg_recent - avg_prior, 2) AS absolute_delta,
ROUND(
(avg_recent - avg_prior) / NULLIF(avg_prior, 0) * 100,
1
) AS pct_change
FROM
(
SELECT
tags['device_id'] AS device_id,
tags['device_type'] AS device_type,
tags['plant_id'] AS plant_id,
AVG(
CASE WHEN "timestamp" >= TIMESTAMP '2025-09-07 06:00:00'
AND "timestamp" < TIMESTAMP '2025-09-07 12:00:00' THEN fields['metric_value'] END
) AS avg_recent,
AVG(
CASE WHEN "timestamp" >= TIMESTAMP '2025-09-07 00:00:00'
AND "timestamp" < TIMESTAMP '2025-09-07 06:00:00' THEN fields['metric_value'] END
) AS avg_prior
FROM
rtia.iot_data
WHERE
"timestamp" >= TIMESTAMP '2025-09-07 00:00:00'
AND "timestamp" < TIMESTAMP '2025-09-07 12:00:00'
GROUP BY
tags['device_id'],
tags['device_type'],
tags['plant_id']
) windows
WHERE
avg_prior IS NOT NULL
AND (avg_recent - avg_prior) / NULLIF(avg_prior, 0) > 0.10
ORDER BY
pct_change DESC
LIMIT
20;
| device_id | device_type | plant_id | avg_prior_6h | avg_recent_6h | absolute_delta | pct_change |
|-------------|--------------------|-----------------|--------------|---------------|----------------|------------|
| DEVICE_0028 | flow_meter | PLANT_HAMBURG | 119.11 | 159.54 | 40.43 | 33.9 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | 0.98 | 1.27 | 0.29 | 29.8 |
| DEVICE_0081 | vibration_sensor | PLANT_STUTTGART | 2.47 | 3.18 | 0.71 | 28.6 |
| DEVICE_0068 | power_meter | PLANT_HAMBURG | 167.81 | 211.99 | 44.18 | 26.3 |
| DEVICE_0039 | temperature_sensor | PLANT_DORTMUND | 47.6 | 59.21 | 11.61 | 24.4 |
| DEVICE_0074 | pressure_sensor | PLANT_DORTMUND | 3.08 | 3.78 | 0.7 | 22.7 |
| DEVICE_0015 | temperature_sensor | PLANT_LEIPZIG | 54.27 | 65.53 | 11.26 | 20.7 |
| DEVICE_0082 | temperature_sensor | PLANT_MUNICH | 47.14 | 56.18 | 9.05 | 19.2 |
| DEVICE_0077 | vibration_sensor | PLANT_MUNICH | 1.26 | 1.49 | 0.23 | 18.2 |
| DEVICE_0083 | power_meter | PLANT_HAMBURG | 281.63 | 325.06 | 43.43 | 15.4 |
B3. NULLIF: Quality Deviation As Percentage of Baseline
Compute how far each device's current quality score deviates from its own all-time average. NULLIF guards against division by zero on devices with no historical baseline.
SELECT
tags['device_id'] AS device_id,
tags['device_type'] AS device_type,
tags['plant_id'] AS plant_id,
ROUND(
AVG(fields['quality_score']) FILTER (
WHERE
"timestamp" < TIMESTAMP '2025-09-07 00:00:00'
),
1
) AS baseline_quality,
ROUND(
AVG(fields['quality_score']) FILTER (
WHERE
"timestamp" >= TIMESTAMP '2025-09-07 00:00:00'
),
1
) AS recent_quality,
ROUND(
(
AVG(fields['quality_score']) FILTER (
WHERE
"timestamp" >= TIMESTAMP '2025-09-07 00:00:00'
) - AVG(fields[ 'quality_score' ]) FILTER (
WHERE
"timestamp" < TIMESTAMP '2025-09-07 00:00:00'
)
) / NULLIF(
AVG(fields['quality_score']) FILTER (
WHERE
"timestamp" < TIMESTAMP '2025-09-07 00:00:00'
),
0
) * 100,
1
) AS quality_change_pct
FROM
rtia.iot_data
GROUP BY
tags['device_id'],
tags['device_type'],
tags['plant_id']
HAVING
AVG(fields['quality_score']) FILTER (
WHERE
"timestamp" < TIMESTAMP '2025-09-07 00:00:00'
) IS NOT NULL
AND AVG(fields['quality_score']) FILTER (
WHERE
"timestamp" >= TIMESTAMP '2025-09-07 00:00:00'
) IS NOT NULL
ORDER BY
quality_change_pct ASC
LIMIT
20;
| device_id | device_type | plant_id | baseline_quality | recent_quality | quality_change_pct |
|-------------|--------------------|-----------------|------------------|----------------|--------------------|
| DEVICE_0046 | temperature_sensor | PLANT_STUTTGART | 94.8 | 85.9 | -9.4 |
| DEVICE_0069 | temperature_sensor | PLANT_DORTMUND | 94.6 | 87.5 | -7.4 |
| DEVICE_0009 | temperature_sensor | PLANT_DORTMUND | 94.5 | 87.5 | -7.3 |
| DEVICE_0035 | power_meter | PLANT_LEIPZIG | 94.2 | 89.4 | -5.2 |
| DEVICE_0033 | temperature_sensor | PLANT_HAMBURG | 94.1 | 90.2 | -4.2 |
| DEVICE_0004 | vibration_sensor | PLANT_DORTMUND | 94.3 | 90.5 | -4.1 |
| DEVICE_0006 | vibration_sensor | PLANT_STUTTGART | 94.4 | 90.7 | -4 |
| DEVICE_0028 | flow_meter | PLANT_HAMBURG | 93.8 | 90.2 | -3.8 |
| DEVICE_0018 | temperature_sensor | PLANT_HAMBURG | 95 | 91.4 | -3.8 |
C. Full text search Queries – access Apache Lucene using SQL
Uses the FULLTEXT index on maintenance_log.notes (standard analyzer). MATCH() scores results by relevance; combine with filters to narrow the set.
C1. Full-text: Find Maintenance Records By Fault Keyword
Locate all work orders that mention calibration in the technician notes
SELECT
work_order_id,
device_id,
maintenance_type,
technician,
completed_date,
notes
FROM
rtia.maintenance_log
WHERE
MATCH(notes, 'calibration')
ORDER BY
completed_date DESC;
| work_order_id | device_id | maintenance_type | technician | completed_date | notes |
|---------------|-------------|------------------|------------|---------------------------|--------------------------------------------------------|
| WO-00463 | DEVICE_0126 | preventive | A. Schmidt | 2025-08-28T00:00:00.000Z | Scheduled lubrication and calibration check. |
| WO-01130 | DEVICE_0322 | preventive | H. Müller | 2025-08-26T00:00:00.000Z | Annual calibration verified against reference standard.|
| WO-00372 | DEVICE_0103 | preventive | E. Braun | 2025-08-24T00:00:00.000Z | Scheduled lubrication and calibration check. |
| WO-00742 | DEVICE_0211 | preventive | H. Müller | 2025-08-10T00:00:00.000Z | Scheduled lubrication and calibration check. |
| WO-01405 | DEVICE_0406 | preventive | A. Schmidt | 2025-08-10T00:00:00.000Z | Scheduled lubrication and calibration check. |
| WO-00833 | DEVICE_0236 | preventive | P. Wagner | 2025-08-08T00:00:00.000Z | Scheduled lubrication and calibration check. |
| WO-00428 | DEVICE_0117 | preventive | P. Wagner | 2025-08-02T00:00:00.000Z | Scheduled lubrication and calibration check. |
| WO-01116 | DEVICE_0319 | preventive | S. Neumann | 2025-07-29T00:00:00.000Z | Annual calibration verified against reference standard.|
C2. FULL-TEXT: Multi-term Search Across Corrective Jobs
Find corrective jobs where notes mention a sensor replacement
SELECT
work_order_id,
device_id,
notes,
cost_eur,
completed_date
FROM
rtia.maintenance_log
WHERE
MATCH(notes, 'sensor replaced')
AND maintenance_type = 'corrective'
ORDER BY
cost_eur DESC;
| work_order_id | device_id | notes | cost_eur | completed_date |
|---------------|-------------|-----------------------------------------------------------------|----------|---------------------------|
| WO-01171 | DEVICE_0335 | Replaced O-ring seal, pressure readings stabilised. | 4902.08 | 2022-12-25T00:00:00.000Z |
| WO-00361 | DEVICE_0099 | Replaced O-ring seal, pressure readings stabilised. | 4834.38 | 2024-09-04T00:00:00.000Z |
| WO-00288 | DEVICE_0079 | Replaced worn sensor element, values restored to normal range. | 4822.72 | 2023-01-29T00:00:00.000Z |
| WO-01217 | DEVICE_0350 | Replaced O-ring seal, pressure readings stabilised. | 4532.44 | 2024-07-08T00:00:00.000Z |
| WO-00987 | DEVICE_0281 | Replaced O-ring seal, pressure readings stabilised. | 4445.86 | 2022-11-03T00:00:00.000Z |
| WO-00969 | DEVICE_0275 | Replaced worn sensor element, values restored to normal range. | 4301.2 | 2024-07-04T00:00:00.000Z |
| WO-01722 | DEVICE_0494 | Replaced worn sensor element, values restored to normal range. | 4255.08 | 2024-04-19T00:00:00.000Z |
| WO-00857 | DEVICE_0242 | Replaced O-ring seal, pressure readings stabilised. | 4240.14 | 2021-11-03T00:00:00.000Z |
C3. FULL-TEXT + JOIN: Fault Keyword Cost By Plant
Which plants have the highest spend on emergency shutdowns?
SELECT
p.plant_name,
p.industry_segment,
COUNT(*) AS matching_jobs,
ROUND(
SUM(m.cost_eur),
0
) AS total_cost_eur
FROM
rtia.maintenance_log m
JOIN rtia.plants p ON m.plant_id = p.plant_id
WHERE
MATCH(m.notes, 'emergency shutdown')
GROUP BY
p.plant_name,
p.industry_segment
ORDER BY
total_cost_eur DESC;
| plant_name | industry_segment | matching_jobs | total_cost_eur |
|----------------------------------|------------------|---------------|----------------|
| Hamburg Chemical Processing | Chemicals | 14 | 77029 |
| Leipzig Logistics Center | Logistics | 13 | 61173 |
| Stuttgart Automotive Assembly | Automotive | 13 | 60507 |
| Munich Electronics Manufacturing | Electronics | 12 | 46544 |
| Dortmund Steel Processing | Steel & Metals | 11 | 45092 |
C4. FULL-TEXT + JOIN: Devices With Recurring Signal Faults
Identify assets with repeated signal or cable issues across all work orders
SELECT
m.device_id,
d.manufacturer,
d.device_type,
COUNT(*) AS matching_jobs,
ROUND(
SUM(m.cost_eur),
0
) AS total_repair_cost
FROM
rtia.maintenance_log m
JOIN rtia.devices d ON m.device_id = d.device_id
WHERE
MATCH(
m.notes, 'signal cable restored'
)
AND m.status = 'completed'
GROUP BY
m.device_id,
d.manufacturer,
d.device_type
ORDER BY
matching_jobs DESC
LIMIT
10;
| device_id | manufacturer | device_type | matching_jobs | total_repair_cost |
|-------------|-----------------|--------------------|---------------|-------------------|
| DEVICE_0381 | Brüel & Kjær | vibration_sensor | 2 | 3603 |
| DEVICE_0059 | Endress+Hauser | pressure_sensor | 2 | 6709 |
| DEVICE_0103 | KROHNE | flow_meter | 2 | 5798 |
| DEVICE_0029 | Bürkert | pressure_sensor | 2 | 7608 |
| DEVICE_0472 | WIKA | temperature_sensor | 2 | 3406 |
| DEVICE_0171 | ifm electronic | vibration_sensor | 2 | 6196 |
| DEVICE_0084 | Endress+Hauser | temperature_sensor | 2 | 7078 |
| DEVICE_0477 | ABB | power_meter | 2 | 5891 |
| DEVICE_0105 | ifm electronic | temperature_sensor | 2 | 5554 |
| DEVICE_0490 | Endress+Hauser | flow_meter | 2 | 6423 |
D. Geospatial
geo_location is a GEO_POINT GENERATED from fields['geo_lon'] / fields['geo_lat'] and stored as [longitude, latitude]. DISTANCE() returns meters. WITHIN() tests point-in-polygon.
D1. GEO: Distance From A Reference Coordinate
How far is each plant from Stuttgart HQ?
SELECT
plant_name,
city,
federal_state,
ROUND(
DISTANCE(
geo_location,
(
SELECT
geo_location
FROM
rtia.locations
WHERE
location_name = 'Stuttgart'
)
) / 1000,
0
) AS km_from_stuttgart
FROM
rtia.plants
ORDER BY
km_from_stuttgart;
| plant_name | city | federal_state | km_from_stuttgart |
|----------------------------------|-----------|----------------------------|-------------------|
| Stuttgart Automotive Assembly | Stuttgart | Baden-Württemberg | 1 |
| Munich Electronics Manufacturing | Munich | Bavaria | 191 |
| Dortmund Steel Processing | Dortmund | North Rhine-Westphalia | 327 |
| Leipzig Logistics Center | Leipzig | Saxony | 364 |
| Hamburg Chemical Processing | Hamburg | Hamburg | 533 |
D2. Geo: Critical Readings Within A Radius
All critical sensor events within 100 km of Frankfurt
SELECT
tags['device_id'] AS device_id,
tags['device_type'] AS device_type,
tags['plant_id'] AS plant_id,
fields['metric_value'] AS metric_value,
tags['metric_unit'] AS metric_unit,
"timestamp",
ROUND(
DISTANCE(
geo_location,
(
SELECT
geo_location
FROM
rtia.locations
WHERE
location_name = 'Frankfurt'
)
) / 1000,
1
) AS km_from_frankfurt
FROM
rtia.iot_data
WHERE
tags['status'] = 'critical'
AND DISTANCE(
geo_location,
(
SELECT
geo_location
FROM
rtia.locations
WHERE
location_name = 'Frankfurt'
)
) < 150000
ORDER BY
km_from_frankfurt
LIMIT
20;
| device_id | device_type | plant_id | metric_value | metric_unit | timestamp | km_from_frankfurt |
|-------------|--------------------|-----------------|--------------|-------------|---------------------------|-------------------|
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 109.03 | C | 2026-01-19T11:02:33.000Z | 149.9 |
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 107.51 | C | 2026-01-19T18:02:37.000Z | 149.9 |
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 107.93 | C | 2026-01-19T13:02:11.000Z | 149.9 |
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 107.99 | C | 2026-01-20T14:03:49.000Z | 149.9 |
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 107.91 | C | 2026-01-19T14:02:44.000Z | 149.9 |
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 107.71 | C | 2026-01-20T21:02:22.000Z | 149.9 |
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 108.21 | C | 2026-01-19T21:03:32.000Z | 149.9 |
| DEVICE_0031 | temperature_sensor | PLANT_STUTTGART | 110.23 | C | 2026-01-21T00:03:54.000Z | 149.9 |
D3. Geo: Fault Density Within A Bounding Polygon
Critical alerts inside the Bavaria bounding box
SELECT
tags['device_type'] AS device_type,
COUNT(*) AS critical_count,
ROUND(
AVG(fields[ 'quality_score' ]),
1
) AS avg_quality
FROM
rtia.iot_data
WHERE
tags['status'] = 'critical'
AND WITHIN(
geo_location,
(
SELECT
geo_area
FROM
rtia.locations
WHERE
location_name = 'Bavaria'
)
)
GROUP BY
tags['device_type']
ORDER BY
critical_count DESC;
| device_type | critical_count | avg_quality |
|--------------------|----------------|-------------|
| temperature_sensor | 1014 | 67.4 |
D4. Geo + JOIN: Critical Alerts With Plant Distance From HQ
Combine sensor alerts with plant coordinates and distance from a central point
SELECT
tags['device_id'] AS device_id,
tags['device_type'] AS device_type,
tags['plant_id'] AS plant_id,
tags['status'] AS status,
fields['metric_value'] AS metric_value,
tags['metric_unit'] AS metric_unit,
geo_location,
ROUND(
DISTANCE(
geo_location,
(
SELECT
geo_location
FROM
rtia.locations
WHERE
location_name = 'Munich'
)
) / 1000,
2
) AS km_from_munich
FROM
rtia.iot_data
WHERE
tags['status'] IN ('warning', 'critical')
ORDER BY
DISTANCE(
geo_location,
(
SELECT
geo_location
FROM
rtia.locations
WHERE
location_name = 'Munich'
)
)
LIMIT
10;
| device_id | device_type | plant_id | status | metric_value | metric_unit | geo_location | km_from_munich |
|-------------|------------------|--------------|---------|--------------|-------------|------------------------|----------------|
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 9.01 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 11.37 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 10.48 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 8.71 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 11.7 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 6.69 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 11.53 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 8.78 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 10.94 | mm/s | [11.5846, 48.1213] | 2.85 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 9.31 | mm/s | [11.5846, 48.1213] | 2.85 |
D5. Geo: Nearest Faulting Device To A Coordinate
Find the closest device currently in warning or critical state to Munich
SELECT
tags['device_id'] as device_id,
tags['device_type'] as device_type,
tags['plant_id'] as plant_id,
tags['status'] as status,
fields['metric_value'] as metric_value,
tags['metric_unit'] as metric_unit,
geo_location,
ROUND(DISTANCE(geo_location, [11.576, 48.137]) / 1000, 2) AS km_from_munich
FROM rtia.iot_data
WHERE tags['status'] IN ('warning', 'critical')
ORDER BY DISTANCE(geo_location, [11.576, 48.137])
LIMIT 10;
| device_id | device_type | plant_id | status | metric_value | metric_unit | geo_location | km_from_munich |
|-------------|------------------|--------------|---------|--------------|-------------|------------------------|----------------|
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 9.01 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 11.37 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 10.48 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 8.71 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 11.7 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 6.69 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 11.53 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 8.78 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 10.94 | mm/s | [11.5846, 48.1213] | 1.86 |
| DEVICE_0047 | vibration_sensor | PLANT_MUNICH | warning | 9.31 | mm/s | [11.5846, 48.1213] | 1.86 |
E. Vector Search
notes_embedding is a FLOAT_VECTOR(384) generated by sentence-transformers/all-MiniLM-L6-v2 from the maintenance_log.notes field.
To make life easier for ourselves we have a table called knn_searches that contains embeddings for the following phrases:
- emergency shutdown thermal runaway critical breach
- calibration drift sensor out of range recalibration
- worn parts replaced mechanical failure vibration
- signal cable damaged transmission restored
- routine inspection preventive maintenance nominal
The query below uses the first phase, which we store as 'thermal event'. There is nothing stopping you adding your own phrases, but that's outside the scope of this scenario.
E1. VECTOR: Semantic Search — Emergency Shutdowns
Query vector encodes: "emergency shutdown thermal runaway critical breach". Returns the 5 work orders whose notes are semantically closest to a thermal emergency event, even if they use different words (e.g."critical fault", "unplanned stoppage", "thermal event contained").
SELECT
work_order_id,
device_id,
maintenance_type,
technician,
completed_date,
notes,
_score AS similarity
FROM
rtia.maintenance_log
WHERE
KNN_MATCH(
notes_embedding,
(
SELECT
embedding
FROM
rtia.knn_searches
WHERE
query_name = 'thermal_event'
),
5
)
ORDER BY
_score DESC;
| work_order_id | device_id | maintenance_type | technician | completed_date | notes | similarity |
|---------------|-------------|------------------|------------|---------------------------|------------------------------------------------------------|-------------|
| WO-00199 | DEVICE_0054 | emergency | P. Wagner | 2022-01-22T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
| WO-00053 | DEVICE_0016 | emergency | P. Wagner | 2023-11-03T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
| WO-00785 | DEVICE_0223 | emergency | H. Müller | 2024-05-15T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
| WO-00076 | DEVICE_0022 | emergency | P. Wagner | 2025-03-10T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
| WO-01216 | DEVICE_0350 | emergency | P. Wagner | 2024-04-15T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
| WO-00086 | DEVICE_0025 | emergency | S. Neumann | 2024-07-12T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
| WO-01250 | DEVICE_0361 | emergency | W. Klein | 2024-10-28T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
| WO-00190 | DEVICE_0052 | emergency | H. Müller | 2024-02-11T00:00:00.000Z | Emergency shutdown triggered by critical threshold breach. | 0.67710334 |
E2. VECTOR + FILTER: Emergency Shutdowns — Emergency Jobs Only
Same thermal-event vector, filtered to maintenance_type = 'emergency'. Demonstrates hybrid: KNN_MATCH narrows by semantic similarity, the SQL predicate then restricts to only emergency work orders; one pass, no subquery. Query vector encodes: "emergency shutdown thermal runaway critical breach"
SELECT
work_order_id,
device_id,
notes,
cost_eur,
completed_date,
_score AS similarity
FROM
rtia.maintenance_log
WHERE
KNN_MATCH(
notes_embedding,
(
SELECT
embedding
FROM
rtia.knn_searches
WHERE
query_name = 'thermal_event'
),
10
)
AND maintenance_type = 'emergency'
ORDER BY
_score DESC;
| work_order_id | device_id | notes | cost_eur | completed_date | similarity |
|---------------|-------------|------------------------------------------------------------|----------|---------------------------|-------------|
| WO-00297 | DEVICE_0081 | Emergency shutdown triggered by critical threshold breach. | 3584.48 | 2022-03-25T00:00:00.000Z | 1.8463299 |
| WO-00327 | DEVICE_0089 | Emergency shutdown triggered by critical threshold breach. | 5067.82 | 2024-05-23T00:00:00.000Z | 1.8463299 |
| WO-00378 | DEVICE_0104 | Emergency shutdown triggered by critical threshold breach. | 3955.06 | 2023-05-27T00:00:00.000Z | 1.8463299 |
| WO-00411 | DEVICE_0113 | Emergency shutdown triggered by critical threshold breach. | 8245.85 | 2022-12-22T00:00:00.000Z | 1.8463299 |
| WO-00593 | DEVICE_0166 | Emergency shutdown triggered by critical threshold breach. | 1104.21 | 2023-07-18T00:00:00.000Z | 1.8463299 |
| WO-01302 | DEVICE_0375 | Emergency shutdown triggered by critical threshold breach. | 1857.87 | 2025-08-22T00:00:00.000Z | 1.8463299 |
| WO-01530 | DEVICE_0441 | Emergency shutdown triggered by critical threshold breach. | 1977.83 | 2024-10-17T00:00:00.000Z | 1.8463299 |
| WO-00605 | DEVICE_0170 | Emergency shutdown triggered by critical threshold breach. | 3618.86 | 2023-09-19T00:00:00.000Z | 1.7602043 |
E3. VECTOR + JOIN: Calibration Faults By Plant
Query vector encodes: "calibration drift sensor out of range recalibration". Finds the top 50 semantically similar work orders and aggregates by plant — surfaces which facilities have the most calibration-related maintenance spend.
SELECT
p.plant_name,
p.industry_segment,
COUNT(*) AS similar_jobs,
ROUND(
SUM(m.cost_eur),
0
) AS total_cost_eur,
ROUND(
AVG(m.cost_eur),
0
) AS avg_cost_per_job
FROM
rtia.maintenance_log m
JOIN rtia.plants p ON m.plant_id = p.plant_id
WHERE
KNN_MATCH(
m.notes_embedding,
(
SELECT
embedding
FROM
rtia.knn_searches
WHERE
query_name = 'calibration_drift'
),
50
)
GROUP BY
p.plant_name,
p.industry_segment
ORDER BY
similar_jobs DESC;
| plant_name | industry_segment | similar_jobs | total_cost_eur | avg_cost_per_job |
|----------------------------------|------------------|--------------|----------------|------------------|
| Munich Electronics Manufacturing | Electronics | 45 | 68709 | 1527 |
| Leipzig Logistics Center | Logistics | 45 | 72859 | 1619 |
| Stuttgart Automotive Assembly | Automotive | 43 | 63265 | 1471 |
| Hamburg Chemical Processing | Chemicals | 36 | 66710 | 1853 |
| Dortmund Steel Processing | Steel & Metals | 31 | 48526 | 1565 |
E4. VECTOR + JOIN: Devices With Recurring Signal / Cable Faults
Query vector encodes: "signal cable damaged transmission restored". Finds assets that appear more than once in the top-100 KNN results — i.e. devices with a repeated signal/cable fault pattern across work orders. These are candidates for a hardware fix rather than another repair cycle.
SELECT
m.device_id,
d.manufacturer,
d.device_type,
d.asset_value_eur,
COUNT(*) AS similar_jobs,
ROUND(
SUM(m.cost_eur),
0
) AS total_repair_cost,
MIN(m.completed_date) AS first_occurrence,
MAX(m.completed_date) AS last_occurrence
FROM
rtia.maintenance_log m
JOIN rtia.devices d ON m.device_id = d.device_id
WHERE
KNN_MATCH(
m.notes_embedding,
(
SELECT
embedding
FROM
rtia.knn_searches
WHERE
query_name = 'signal_cable'
),
100
)
AND m.status = 'completed'
GROUP BY
m.device_id,
d.manufacturer,
d.device_type,
d.asset_value_eur
HAVING
COUNT(*) > 1
ORDER BY
similar_jobs DESC,
total_repair_cost DESC
LIMIT
15;
| device_id | manufacturer | device_type | asset_value_eur | similar_jobs | total_repair_cost | first_occurrence | last_occurrence |
|-------------|-----------------|--------------------|-----------------|--------------|-------------------|---------------------------|---------------------------|
| DEVICE_0224 | Bürkert | pressure_sensor | 1367.52 | 4 | 15365 | 2021-12-08T00:00:00.000Z | 2024-02-05T00:00:00.000Z |
| DEVICE_0106 | Endress+Hauser | temperature_sensor | 1387.13 | 4 | 14395 | 2022-08-28T00:00:00.000Z | 2025-03-05T00:00:00.000Z |
| DEVICE_0180 | ifm electronic | temperature_sensor | 840.14 | 4 | 11682 | 2021-10-29T00:00:00.000Z | 2023-07-05T00:00:00.000Z |
| DEVICE_0196 | Siemens | temperature_sensor | 1510.56 | 3 | 16759 | 2022-10-17T00:00:00.000Z | 2023-08-29T00:00:00.000Z |
| DEVICE_0029 | Bürkert | pressure_sensor | 1285.53 | 3 | 12166 | 2021-09-27T00:00:00.000Z | 2025-03-14T00:00:00.000Z |
| DEVICE_0360 | WIKA | temperature_sensor | 1080.97 | 3 | 10693 | 2024-05-04T00:00:00.000Z | 2025-03-30T00:00:00.000Z |
| DEVICE_0182 | ifm electronic | vibration_sensor | 2925.09 | 3 | 10009 | 2024-06-24T00:00:00.000Z | 2025-07-05T00:00:00.000Z |
F. Hybrid Search
F1. Hybrid Search: Vector + Full-text Combined Score
Combines KNN_MATCH (semantic similarity) and MATCH (keyword relevance) with OR. CrateDB merges both signals into a combined_score:
- Records matching only the vector rank by cosine similarity alone.
- Records matching only the keyword rank by BM25 relevance alone.
- Records matching both receive a boosted combined score and surface first.
This is the key advantage over running two separate queries and merging results.
- Vector encodes: "worn parts replaced mechanical failure vibration"
- Keyword: 'vibration' explicitly boosts notes that name the symptom directly.
- Together: finds all vibration-related work orders whether they use that exact word or describe the same concept differently ("excessive oscillation", "bearing noise", "abnormal movement").
SELECT
work_order_id,
device_id,
maintenance_type,
completed_date,
notes,
_score AS combined_score
FROM rtia.maintenance_log
WHERE KNN_MATCH(notes_embedding, (SELECT embedding FROM rtia.knn_searches WHERE query_name = 'mechanical_failure'), 20)
OR MATCH(notes, 'vibration')
ORDER BY _score DESC
LIMIT 15;
| work_order_id | device_id | maintenance_type | completed_date | notes | combined_score |
|---------------|-------------|------------------|---------------------------|---------------------------------------------------|----------------|
| WO-00059 | DEVICE_0018 | corrective | 2024-08-18T00:00:00.000Z | Tightened mounting bolts, vibration level reduced. | 1.7588544 |
| WO-00074 | DEVICE_0022 | corrective | 2025-03-16T00:00:00.000Z | Tightened mounting bolts, vibration level reduced. | 1.7588544 |
| WO-00049 | DEVICE_0014 | corrective | 2025-01-19T00:00:00.000Z | Tightened mounting bolts, vibration level reduced. | 1.383508 |
| WO-00138 | DEVICE_0039 | corrective | 2024-04-04T00:00:00.000Z | Tightened mounting bolts, vibration level reduced. | 1.383508 |
| WO-00170 | DEVICE_0048 | corrective | 2023-12-19T00:00:00.000Z | Tightened mounting bolts, vibration level reduced. | 1.383508 |
| WO-00173 | DEVICE_0048 | corrective | 2025-03-21T00:00:00.000Z | Tightened mounting bolts, vibration level reduced. | 1.383508 |
| WO-00298 | DEVICE_0081 | corrective | 2024-05-31T00:00:00.000Z | Tightened mounting bolts, vibration level reduced. | 1.383508 |