From a5380aece610186860a5d1bc29f1e6a4ca3754a8 Mon Sep 17 00:00:00 2001 From: kianiadee Date: Thu, 11 Jun 2026 23:49:37 +0300 Subject: [PATCH] fix(schema): one device per fill in v_fuel_fills (LATERAL + LIMIT 1) A plate can map to multiple tracksolid.devices rows (vehicle re-fitted with a new tracker), so the plain LEFT JOIN fanned out and double-counted litres/spend (3345 view rows for 1888 live records). LATERAL ... ORDER BY enabled_flag, updated_at LIMIT 1 picks one device per fill. Applied to prod as migration 02; 01 updated so fresh installs are correct. Verified: 1888 rows, 1775 matched. Co-Authored-By: Claude Opus 4.8 --- migrations/01_fuel_schema.sql | 16 ++++++++-- migrations/02_fuel_fills_dedupe_join.sql | 38 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 migrations/02_fuel_fills_dedupe_join.sql diff --git a/migrations/01_fuel_schema.sql b/migrations/01_fuel_schema.sql index fa6689c..1b89310 100644 --- a/migrations/01_fuel_schema.sql +++ b/migrations/01_fuel_schema.sql @@ -157,7 +157,7 @@ CREATE OR REPLACE VIEW reporting.v_fuel_fills AS d.vehicle_number, d.cost_centre, d.assigned_city, - d.driver_name AS assigned_driver, + d.assigned_driver, d.imei, r.department, r.driver, @@ -166,7 +166,19 @@ CREATE OR REPLACE VIEW reporting.v_fuel_fills AS r.fuel_type, r.odometer FROM fuel.records r - LEFT JOIN tracksolid.devices d ON fuel.norm_plate(d.vehicle_number) = r.plate + -- LATERAL + LIMIT 1: a plate can map to more than one devices row (vehicle + -- re-fitted with a new tracker over time). Pick exactly ONE — prefer an + -- enabled, most-recently-updated device — so each fill yields a single row + -- (a plain LEFT JOIN fans out and double-counts litres/spend). + LEFT JOIN LATERAL ( + SELECT dv.vehicle_number, dv.cost_centre, dv.assigned_city, + dv.driver_name AS assigned_driver, dv.imei + FROM tracksolid.devices dv + WHERE r.plate IS NOT NULL + AND fuel.norm_plate(dv.vehicle_number) = r.plate + ORDER BY dv.enabled_flag DESC NULLS LAST, dv.updated_at DESC NULLS LAST + LIMIT 1 + ) d ON true WHERE r.deleted_at IS NULL; -- ── per-vehicle fuel efficiency: km/litre from consecutive odometer readings ── diff --git a/migrations/02_fuel_fills_dedupe_join.sql b/migrations/02_fuel_fills_dedupe_join.sql new file mode 100644 index 0000000..76753d2 --- /dev/null +++ b/migrations/02_fuel_fills_dedupe_join.sql @@ -0,0 +1,38 @@ +-- 02_fuel_fills_dedupe_join.sql — fleetfuel · fix v_fuel_fills row fan-out +-- ───────────────────────────────────────────────────────────────────────────── +-- A plate can map to more than one tracksolid.devices row (a vehicle re-fitted +-- with a new tracker keeps the same number plate), so the migration-01 plain +-- LEFT JOIN produced multiple rows per fill and double-counted litres / spend +-- (v_fuel_fills had ~3345 rows for ~1888 live records). Replace the join with a +-- LATERAL ... LIMIT 1 that picks exactly one device per fill (prefer enabled, +-- most-recently-updated), so each fill yields a single row. Columns unchanged, +-- so dependent reporting.v_fuel_efficiency stays valid. Idempotent. +-- ───────────────────────────────────────────────────────────────────────────── + +CREATE OR REPLACE VIEW reporting.v_fuel_fills AS + SELECT r.id, + r.record_datetime, + r.record_datetime::date AS fuel_date, + r.plate, + d.vehicle_number, + d.cost_centre, + d.assigned_city, + d.assigned_driver, + d.imei, + r.department, + r.driver, + r.liters, + r.amount, + r.fuel_type, + r.odometer + FROM fuel.records r + LEFT JOIN LATERAL ( + SELECT dv.vehicle_number, dv.cost_centre, dv.assigned_city, + dv.driver_name AS assigned_driver, dv.imei + FROM tracksolid.devices dv + WHERE r.plate IS NOT NULL + AND fuel.norm_plate(dv.vehicle_number) = r.plate + ORDER BY dv.enabled_flag DESC NULLS LAST, dv.updated_at DESC NULLS LAST + LIMIT 1 + ) d ON true + WHERE r.deleted_at IS NULL;