功能:完善里程边界与氢耗流式统计

This commit is contained in:
lingniu
2026-09-02 14:05:04 +08:00
parent 4201878c35
commit 8759668d39
23 changed files with 1638 additions and 159 deletions
@@ -0,0 +1,29 @@
-- Persist the end-of-day cumulative odometer independently of the source that
-- wins the daily-distance projection. This prevents GPS-derived daily mileage
-- from being exposed as terminal odometer mileage.
ALTER TABLE vehicle_daily_mileage
ADD COLUMN day_end_total_mileage_km DECIMAL(18,3) NULL AFTER latest_total_mileage_km;
-- Backfill every historical day with the best valid terminal/source cumulative
-- reading. Non-GPS evidence always wins; GPS remains the fallback only where
-- it is the sole available cumulative source.
UPDATE vehicle_daily_mileage m
SET m.day_end_total_mileage_km = COALESCE((
SELECT total_candidate.latest_total_mileage_km
FROM vehicle_daily_mileage_source total_candidate
WHERE total_candidate.vin=m.vin
AND total_candidate.stat_date=m.stat_date
AND total_candidate.protocol=m.protocol
AND total_candidate.quality_status='OK'
AND total_candidate.latest_total_mileage_km IS NOT NULL
AND total_candidate.latest_total_mileage_km>=0
ORDER BY
CASE WHEN COALESCE(total_candidate.quality_reason,'')='gps_coordinate_accumulation' THEN 1 ELSE 0 END,
CASE WHEN total_candidate.latest_total_mileage_km>total_candidate.daily_mileage_km THEN 0 ELSE 1 END,
total_candidate.is_selected DESC,
total_candidate.latest_event_time DESC,
total_candidate.sample_count DESC,
total_candidate.source_key ASC
LIMIT 1
),m.latest_total_mileage_km)
WHERE m.day_end_total_mileage_km IS NULL;
@@ -0,0 +1,24 @@
CREATE TABLE IF NOT EXISTS vehicle_open_hydrogen_segment_stream_state (
vin VARCHAR(64) NOT NULL,
stat_date DATE NOT NULL,
source_endpoint VARCHAR(128) NOT NULL DEFAULT '',
finalized_consumption_kg DECIMAL(18,3) NOT NULL DEFAULT 0,
projected_consumption_kg DECIMAL(18,3) NOT NULL DEFAULT 0,
sample_count BIGINT UNSIGNED NOT NULL DEFAULT 0,
refuel_count INT UNSIGNED NOT NULL DEFAULT 0,
abnormal_drop_count INT UNSIGNED NOT NULL DEFAULT 0,
eligible_interval_count BIGINT UNSIGNED NOT NULL DEFAULT 0,
qualified_segment_count INT UNSIGNED NOT NULL DEFAULT 0,
last_mass_kg DECIMAL(18,3) NOT NULL DEFAULT 0,
last_event_time DATETIME(3) NOT NULL,
last_event_id VARCHAR(128) NOT NULL DEFAULT '',
state_json JSON NOT NULL,
calculation_method VARCHAR(48) NOT NULL DEFAULT 'PRESSURE_NIST_SEGMENT_MEDIAN_5',
quality_status VARCHAR(24) NOT NULL DEFAULT 'NO_DATA',
quality_reason VARCHAR(255) NOT NULL DEFAULT '有效工作段关键帧不足10条',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (vin, stat_date),
INDEX idx_hydrogen_segment_stream_date_quality (stat_date, quality_status, vin),
CONSTRAINT chk_hydrogen_segment_stream_quality CHECK (quality_status IN ('OK', 'NO_DATA', 'SUSPECT'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
@@ -0,0 +1,34 @@
CREATE TABLE IF NOT EXISTS vehicle_hydrogen_energy_parameter (
vin VARCHAR(64) NOT NULL,
battery_capacity_kwh DECIMAL(12,3) NOT NULL,
hydrogen_energy_kwh_per_kg DECIMAL(12,3) NOT NULL DEFAULT 16.000,
confirmed_by VARCHAR(96) NOT NULL DEFAULT '',
source_note VARCHAR(255) NOT NULL DEFAULT '',
effective_from DATE NOT NULL,
effective_to DATE NULL,
active TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (vin, effective_from),
INDEX idx_hydrogen_energy_parameter_active (active, effective_from, effective_to, vin),
CONSTRAINT chk_hydrogen_energy_parameter_capacity CHECK (battery_capacity_kwh > 0 AND battery_capacity_kwh <= 500),
CONSTRAINT chk_hydrogen_energy_parameter_conversion CHECK (hydrogen_energy_kwh_per_kg > 0 AND hydrogen_energy_kwh_per_kg <= 50),
CONSTRAINT chk_hydrogen_energy_parameter_dates CHECK (effective_to IS NULL OR effective_to >= effective_from)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE vehicle_open_daily_energy
ADD COLUMN raw_consumption_kg DECIMAL(18,3) NULL AFTER consumption_kg,
ADD COLUMN battery_soc_delta_pct DECIMAL(10,3) NULL AFTER raw_consumption_kg,
ADD COLUMN battery_discharge_kwh DECIMAL(18,3) NULL AFTER battery_soc_delta_pct,
ADD COLUMN battery_equivalent_kg DECIMAL(18,3) NULL AFTER battery_discharge_kwh,
ADD COLUMN soc_balanced_consumption_kg DECIMAL(18,3) NULL AFTER battery_equivalent_kg,
ADD COLUMN mixed_mileage_km DECIMAL(18,3) NOT NULL DEFAULT 0 AFTER soc_balanced_consumption_kg,
ADD COLUMN pure_electric_mileage_km DECIMAL(18,3) NOT NULL DEFAULT 0 AFTER mixed_mileage_km,
ADD COLUMN consumption_kg_per_100km DECIMAL(18,3) NULL AFTER pure_electric_mileage_km,
ADD COLUMN soc_balanced_kg_per_100km DECIMAL(18,3) NULL AFTER consumption_kg_per_100km,
ADD COLUMN charge_count INT UNSIGNED NOT NULL DEFAULT 0 AFTER refuel_count,
ADD COLUMN valid_segment_count INT UNSIGNED NOT NULL DEFAULT 0 AFTER charge_count,
ADD COLUMN invalid_segment_count INT UNSIGNED NOT NULL DEFAULT 0 AFTER valid_segment_count,
ADD COLUMN algorithm_version VARCHAR(64) NOT NULL DEFAULT 'PRESSURE_NIST_SEGMENT_MEDIAN_5' AFTER invalid_segment_count,
ADD COLUMN parameter_json JSON NULL AFTER algorithm_version,
ADD COLUMN evidence_json JSON NULL AFTER parameter_json;