Hier erkläre ich dir, wie du Ausreißer oder generell gesprochen falsche Statistiken deiner Home Assistant Entitäten korrigieren kannst.
Das ist vor allem für das Energiedashboard wichtig, kann aber auch für andere Entitäten relevant sein solltest du dich beispielsweise für Auswertungen auf die Home Assistant Statistiken verlassen.
Lass uns gemeinsam eintauchen und herausfinden, welche 3 Möglichkeiten es dafür gibt!
Inhaltsverzeichnis
- Voraussetzungen
- SQL-Kommandos für Möglichkeit 3
- Links zu SQL-Skripten
- Hinweis zu geänderten Einheiten
- Mehr Skripte zum modifizieren/korrigieren der Statistiken
- 2026 – Mein neues Skript zum korrigieren vom Energiedashboard
- Skript-Toolbox
- Fazit
Voraussetzungen
Home Assistant muss schon installiert sein, auf welcher Hardware spielt keine Rolle.
Außerdem sollte deine Datenbank auf SQLite laufen (nur für Maria-DB nutzer relevant, SQLite ist der Systemstandard)
SQL-Kommandos für Möglichkeit 3
Zuerst musst du mit dem Kommando SELECT * FROM "statistics_meta" where statistic_id LIKE "%strom%" herausfinden, welche ID (ganz linke spalte) deine Entität in der Meta-Tabelle hat. Hier wird nach dem Platzhalter Strom innerhalb des Entitäts-Namens gesucht.
Anschließend kopierst du dir die ID in ein Textdokument (Hier im Beispiel 18)
Danach suchen wir uns mit dem SQL-Query SELECT * FROM "statistics" where metadata_id = 18 Order BY state DESC den größten Statistischen Wert der Entität aus der Statistiktabelle raus.
ASC anstatt DESC gibt uns den kleinsten statistischen wert ganz oben aus 😉
Links zu SQL-Skripten
Für erweiterte Datenbereinigung oder hinzufügen von Statistischen Einträgen relevant. Nicht zu empfehlen, wenn man keinen Plan von SQL hat, weil man schnell mehr kaputt machen kann als vorher war 😉
- https://community.home-assistant.io/t/fix-bad-data-in-energy-tab/347792/53
- https://community.home-assistant.io/t/recalculate-statistics-table-sum-to-fix-wrong-energy-data/371334
Hinweis zu geänderten Einheiten
Ganz nebenbei bemerkt habe ich im Video vergessen, eine Möglichkeit zu erwähnen. Mit dem Statistik-Tool kann man Einheiten korrigieren, wenn sich die Einheit eines Sensors mal geändert haben sollte.
Beispiel: Man legt einen Template-Sensor an, vergisst die Einheit zu setzen und ergänzt diese danach erst (nach dem initialen Anlegen des Sensors). Somit weiß Home Assistant nicht mehr, welches die „richtige“ der beiden Einheiten (keine / die neue Einheit) ist.
Beheben kann man das Problem aber einfacher, als es zu erklären 😉:

Mehr Skripte zum modifizieren/korrigieren der Statistiken
kWh anstatt Wh – Beispiel
Du hast einen Sensor angelegt, der eigentlich Wh angibt jedoch hast du versehentlich diesen Sensor mit kWh erstellt. Nun musst du alle bisherigen werte durch 1000 teilen, damit das irgendwie noch Sinn macht
- Meta-ID suchen:
SELECT * FROM "statistics_meta" where statistic_id LIKE "%solar%"
- Daten anzeigen, das müssen wir in 2 Tabellen (jeweils) machen:
SELECT * FROM statistics WHERE metadata_id = 779 SELECT * FROM statistics_short_term WHERE metadata_id = 779
- Die Ziele finden, bis zu welcher das Problem bestand (falls du das Template oder die Einheit inzwischen angepasst hast, und über das Statistik-Tool wurde dir nicht angeboten die bisherigen Werte zu ändern) und dann alle werte kleiner als der Timestamp anzeigen:
SELECT * FROM statistics WHERE metadata_id = 779 AND created_ts < 1720942810.3191178 SELECT * FROM statistics_short_term WHERE metadata_id = 779 AND created_ts < 1720942810.3191178
- Werte verändern, in diesem Beispiel werden diese durch 1000 geteilt (Wattstunden in Kilowattstunden umrechnen). Sind hier natürlich auch wieder 2 Statements für jeweils eine der Tabellen:
UPDATE "statistics" SET state = state / 1000, sum = sum / 1000 WHERE metadata_id = 779 AND created_ts < 1720942810.3191178 UPDATE "statistics_short_term" SET state = state / 1000, sum = sum / 1000 WHERE metadata_id = 779 AND created_ts < 1720942810.3191178
2026 – Mein neues Skript zum korrigieren vom Energiedashboard
Ich hatte bei einem bekannten das Problem, dass die Werte im Energiedashboard von einem Lesekopf verfälscht waren. Hier wurde teilweise 1-2 mal pro Tag der Zählerstand genullt, was dazu führt, dass in Home Assistant die Statistiken direkt danach den gesamten Verbrauch des Stromzählers als verbrauch zählen.
Daraufhin habe ich 2 Skripte für das SQLLite-Web Addon geschrieben.
Eines zum Finden auffälliger Verbräuche und ein 2. Skript, was die gefundenen Verbräuche mathematisch bereinigt. Ist getestet mit einem normalen Stromverbrauchszähler (Einspeisung und Netzbezug), sollte aber auch für alle anderen Statistiken funktionieren.
Wichtig ist folgendes:
- Vorher UNBEDINGT ein Backup machen und bei Bedarf wiederherstellen! Ich übernehme keine Garantie für Funktion des Skriptes, verlorene Daten oder sonst was.
- Die Range, also ab welchem Wert die Werte als „zu korrigieren“ angesehen werden, ist in beiden Skripten (Finden der Werte (1) und Korrigieren der Werte (2)) statisch auf 100 eingestellt. Für Stromzähler von Privatwohnungen ganz passen, für Gewerbe-Strom oder Wasserzähler entsprechend anpassen.
- Die korrekten Werte werden mathematisch aus dem Stand davor und danach ermittelt.
1. Skript – Finden der Werte
Mit diesem Skript kannst du erstmal schauen, was das 2. Skript korrigieren würde, zumindest die ersten 1500 Zeilen.
Wenn du in diesem Skript etwas anpasst, weil deine Werte oder Entität-ID anders sind/ist, denk daran, dass dann auch im Skript zum korrigieren der Werte zu machen!
WITH error_marks AS (
-- 1. Wir finden die Fehlerstellen mit gelockertem Filter
SELECT
s.id,
s.start_ts,
-- Berechnung des Offsets: Summen-Sprung MINUS echter Zähler-Zuwachs
(s.sum - s_prev.sum) - (s.state - s_prev.state) as offset_delta
FROM statistics s
JOIN statistics s_prev ON s.metadata_id = s_prev.metadata_id
AND s_prev.start_ts = (SELECT MAX(start_ts) FROM statistics WHERE metadata_id = s.metadata_id AND start_ts < s.start_ts)
WHERE s.metadata_id = (SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.netzeinspeisung')
-- Wir suchen Summen-Sprünge über 100...
AND (s.sum - s_prev.sum) > 100
-- ...während der echte Zählerstand sich im plausiblen Rahmen (0-1000) bewegte
AND (s.state - s_prev.state) BETWEEN 0 AND 1000
),
all_data AS (
SELECT
s.id,
s.start_ts,
s.sum as original_sum,
s.state,
em.offset_delta
FROM statistics s
LEFT JOIN error_marks em ON s.id = em.id
WHERE s.metadata_id = (SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.netzeinspeisung')
)
SELECT
datetime(start_ts, 'unixepoch', 'localtime') as zeitpunkt,
state as zählerstand,
ROUND(original_sum, 1) as summe_alt,
-- Kumulierung der Offsets über die Zeit
ROUND(SUM(COALESCE(offset_delta, 0)) OVER (ORDER BY start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 1) as kumulierter_fehler,
-- Berechnung der neuen Ziel-Summe
ROUND(original_sum - SUM(COALESCE(offset_delta, 0)) OVER (ORDER BY start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 1) as summe_neu_vorgeschlagen
FROM all_data
ORDER BY start_ts DESC
LIMIT 1500;
2. Skript – Korrigieren der Werte
WITH target_sensor AS (
SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.netzeinspeisung'
),
error_marks AS (
-- 1. Identifikation der Fehler-Zeitpunkte
SELECT
s.id,
s.start_ts,
((s.sum - s_prev.sum) - (s.state - s_prev.state)) as offset_delta
FROM statistics s
JOIN statistics s_prev ON s.metadata_id = s_prev.metadata_id
AND s_prev.start_ts = (SELECT MAX(start_ts) FROM statistics WHERE metadata_id = s.metadata_id AND start_ts < s.start_ts)
WHERE s.metadata_id = (SELECT id FROM target_sensor)
-- Wir korrigieren Summen-Sprünge über 100...
AND (s.sum - s_prev.sum) > 100
-- ...während der echte Zählerstand sich im plausiblen Rahmen (0-1000) bewegte
AND (s.state - s_prev.state) BETWEEN 0 AND 1000
),
correction_map AS (
-- 2. Zuordnung jeder ID zu ihrem spezifischen Korrektur-Offset
SELECT
s.id,
SUM(COALESCE(em.offset_delta, 0)) OVER (ORDER BY s.start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as total_offset
FROM statistics s
LEFT JOIN error_marks em ON s.id = em.id
WHERE s.metadata_id = (SELECT id FROM target_sensor)
)
-- 3. Das eigentliche Update
UPDATE statistics
SET sum = sum - (
SELECT total_offset
FROM correction_map
WHERE correction_map.id = statistics.id
)
WHERE id IN (SELECT id FROM correction_map);
3. Bonus-Skripte – Kosten bereinigen
Dieses 3. Skript kann, NACHDEM alle Statistiken bereinigt sind (entweder manuell oder durch die Skripte oben), die Stromverbrauchskosten des Energiedashboards korrigieren.
Das Skript würde ich insgesamt noch als experimentell bezeichnen, hat bei mir aber funktioniert. Muss nicht heißen, dass das bei dir auch so ist 😅
Die beiden Sensoren hier im Beispiel sind sensor.netzbezug (der kWh-Sensor des Stromzählers) und sensor.netzbezug_cost (der Automatisch vom Energiedashboard angelegte zugehörige Sensor, mit den Kosten, die hier korrigiert werden)
Select-Statement (Nur gucken, nix anfassen)
WITH
-- 1. Definition der beiden betroffenen Sensoren
target_ids AS (
SELECT
(SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.netzbezug') as energy_id,
(SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.netzbezug_cost') as cost_id
),
-- 2. Holen der Energie-Daten (wir nutzen die bereits korrigierte 'sum'-Spalte)
energy_data AS (
SELECT
start_ts,
(sum - LAG(sum) OVER (ORDER BY start_ts)) as energy_delta
FROM statistics, target_ids
WHERE metadata_id = energy_id
),
-- 3. Holen der Kosten-Daten
cost_data AS (
SELECT
id, start_ts, sum,
(sum - LAG(sum) OVER (ORDER BY start_ts)) as cost_delta
FROM statistics, target_ids
WHERE metadata_id = cost_id
),
-- 4. Zusammenführung und Ermittlung des realen Preises (aus sauberen Daten)
combined AS (
SELECT
c.id, c.start_ts, c.sum as cost_sum, c.cost_delta,
e.energy_delta,
CASE
WHEN c.cost_delta > 0 AND c.cost_delta < 2 AND e.energy_delta > 0
THEN c.cost_delta / e.energy_delta
ELSE NULL
END as calculated_unit_price
FROM cost_data c
JOIN energy_data e ON c.start_ts = e.start_ts
),
-- 5. Durchschnittspreis festlegen
reference_price AS (
SELECT AVG(calculated_unit_price) as val FROM combined WHERE calculated_unit_price IS NOT NULL
),
-- 6. Fehlerstellen exakt berechnen
error_marks AS (
SELECT
c.id,
c.start_ts,
-- Fehler = Tatsächlicher Sprung - (Echter Verbrauch * Preis)
c.cost_delta - (COALESCE(c.energy_delta, 0) * (SELECT val FROM reference_price)) as offset_delta
FROM combined c
WHERE c.cost_delta > 10.0 -- Schwelle für Kostensprung
)
-- 7. Die finale "perfekte" Vorschau
SELECT
datetime(c.start_ts, 'unixepoch', 'localtime') as zeitpunkt,
ROUND(c.energy_delta, 3) as echter_verbrauch,
ROUND(c.cost_sum, 2) as kosten_summe_alt,
ROUND(SUM(COALESCE(em.offset_delta, 0)) OVER (ORDER BY c.start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 2) as kumulierter_fehler_euro,
ROUND(c.cost_sum - SUM(COALESCE(em.offset_delta, 0)) OVER (ORDER BY c.start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 2) as kosten_summe_perfekt
FROM combined c
LEFT JOIN error_marks em ON c.id = em.id
ORDER BY c.start_ts DESC
LIMIT 1500;
Update-Statement
WITH
-- 1. IDs festlegen
target_ids AS (
SELECT
(SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.netzbezug') as energy_id,
(SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.netzbezug_cost') as cost_id
),
-- 2. Energie-Deltas (bereits korrigiert)
energy_data AS (
SELECT
start_ts,
(sum - LAG(sum) OVER (ORDER BY start_ts)) as energy_delta
FROM statistics, target_ids
WHERE metadata_id = energy_id
),
-- 3. Kosten-Deltas
cost_data AS (
SELECT
id, start_ts, sum,
(sum - LAG(sum) OVER (ORDER BY start_ts)) as cost_delta
FROM statistics, target_ids
WHERE metadata_id = cost_id
),
-- 4. Preis ermitteln aus sauberen Stunden (Sprung < 2€)
reference_price AS (
SELECT AVG(c.cost_delta / e.energy_delta) as val
FROM cost_data c
JOIN energy_data e ON c.start_ts = e.start_ts
WHERE c.cost_delta > 0 AND c.cost_delta < 2.0 AND e.energy_delta > 0
),
-- 5. Exakten Fehler pro Stunde berechnen
error_marks AS (
SELECT
c.id,
c.start_ts,
-- Fehler = Tatsächlicher Sprung - (Echter Verbrauch * Durchschnittspreis)
c.cost_delta - (COALESCE(e.energy_delta, 0) * (SELECT val FROM reference_price)) as offset_delta
FROM cost_data c
JOIN energy_data e ON c.start_ts = e.start_ts
WHERE c.cost_delta > 10.0 -- Schwelle für unplausible Kosten
),
-- 6. Kumulierter Korrekturwert für jede Zeile der Tabelle
correction_map AS (
SELECT
s.id,
SUM(COALESCE(em.offset_delta, 0)) OVER (ORDER BY s.start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as total_offset
FROM statistics s
LEFT JOIN error_marks em ON s.id = em.id
WHERE s.metadata_id = (SELECT cost_id FROM target_ids)
)
-- 7. Das finale Update
UPDATE statistics
SET sum = sum - (
SELECT total_offset
FROM correction_map
WHERE correction_map.id = statistics.id
)
WHERE id IN (SELECT id FROM correction_map);
Skript zum korrigieren vom einzelnen Geräte-Verbräuchen
Außerdem habe ich auch noch 2 Skripte erstellt um den Verbrauch einzelner Geräte wieder zu korrigieren. Denn z.B. bei manchen Shelly-Firmwares kommt es ohne ersichtlichen Grund vor, dass auf einmal z.B. 3000 kWh Verbrauch gemeldet werden. Ein zurücksetzen der Counter des Shelly-Gerätes schafft da oft Abhilfe.
Natürlich alles auf eigene Gefahr -> Kein Backup kein Mitleid! ⚠️
Die beiden Skripte zeigen (Skript 1) und korrigieren Skript 2 unplausibel hohe werte (über 1000 kwh), in dem diese einfach auf 0 gesetzt werden. Klar, ist nicht perfekt, aber für Einzelgeräte statistisch gesehen vernachlässigbar.
1. Skript – Finden der Werte
Wenn du in diesem Skript etwas anpasst, weil deine Werte oder Entität-ID anders sind/ist, denk daran, dass dann auch im Skript zum korrigieren der Werte zu machen!
WITH target_sensor AS (
-- HIER die Entity-ID des Shellys eintragen
SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.licht_spiegelschrank_energie'
),
error_marks AS (
-- 1. Wir finden die "Phantom-Sprünge" (größer als 1000 kWh)
SELECT
s.id,
s.start_ts,
-- Wir definieren den gesamten Zuwachs dieser Stunde als Fehler
(s.sum - s_prev.sum) as offset_delta
FROM statistics s
JOIN statistics s_prev ON s.metadata_id = s_prev.metadata_id
AND s_prev.start_ts = (SELECT MAX(start_ts) FROM statistics WHERE metadata_id = s.metadata_id AND start_ts < s.start_ts)
WHERE s.metadata_id = (SELECT id FROM target_sensor)
AND (s.sum - s_prev.sum) > 1000 -- Schwelle für den kWh-Fehler
),
all_data AS (
SELECT
s.id,
s.start_ts,
s.sum as original_sum,
em.offset_delta
FROM statistics s
LEFT JOIN error_marks em ON s.id = em.id
WHERE s.metadata_id = (SELECT id FROM target_sensor)
)
SELECT
datetime(start_ts, 'unixepoch', 'localtime') as zeitpunkt,
ROUND(original_sum, 2) as summe_alt,
ROUND(SUM(COALESCE(offset_delta, 0)) OVER (ORDER BY start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 2) as abgezogener_fehler,
ROUND(original_sum - SUM(COALESCE(offset_delta, 0)) OVER (ORDER BY start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 2) as summe_neu_geglättet
FROM all_data
ORDER BY start_ts DESC
LIMIT 500;
2. Skript – Korrigieren der Werte
WITH target_sensor AS (
-- HIER die Entity-ID des Shellys eintragen
SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.licht_spiegelschrank_energie'
),
error_marks AS (
SELECT
s.id,
s.start_ts,
-- Wir definieren den gesamten Zuwachs dieser Stunde als Fehler
(s.sum - s_prev.sum) as offset_delta
FROM statistics s
JOIN statistics s_prev ON s.metadata_id = s_prev.metadata_id
AND s_prev.start_ts = (SELECT MAX(start_ts) FROM statistics WHERE metadata_id = s.metadata_id AND start_ts < s.start_ts)
WHERE s.metadata_id = (SELECT id FROM target_sensor)
AND (s.sum - s_prev.sum) > 1000 -- Schwelle für den kWh-Fehler
),
correction_map AS (
SELECT
s.id,
SUM(COALESCE(em.offset_delta, 0)) OVER (ORDER BY s.start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as total_offset
FROM statistics s
LEFT JOIN error_marks em ON s.id = em.id
WHERE s.metadata_id = (SELECT id FROM target_sensor)
)
UPDATE statistics
SET sum = sum - (
SELECT total_offset
FROM correction_map
WHERE correction_map.id = statistics.id
)
WHERE id IN (SELECT id FROM correction_map);
Danach müssen wir noch die Kurzzeitstatistiken des Sensors leeren 👇, damit nicht der nächste Eintrag (in der jetzt korrigierten) Langzeit-Statistik wieder mit dem falschen Summen-Wert gemacht wird. (Ansonsten hast du direkt in der nächsten Stunde nach der Korrektur einen gigantischen Spike im Energy-Dashboard)
DELETE FROM statistics_short_term WHERE metadata_id = (SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.licht_spiegelschrank_energie');
5 Minuten später muss man dann noch den neusten Eintrag der Statistik-Tabelle korrigieren, da dieser nun negativ sein wird. Das liegt an der Art, wie die short_term und normalen Statistiken funktionieren.
Wie dem auch sein: Einfach 5 Minuten nach dem korrigieren des Sensors und löschen der Kurzzeit-Statistik in den Entwicklerwerkzeugen mit dem Statistik-Tool 👇 den negativen Eintrag auf 0 setzen, danach sollte es dann zukünftig passen 👍
Skript-Toolbox
Hilfreiche Skripte zum anzeigen der Statistiken usw.
Short-Term Statistik eines Sensors anzeigen
SELECT
datetime(start_ts, 'unixepoch', 'localtime') as zeitpunkt,
state,
sum
FROM statistics_short_term
WHERE metadata_id = (SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.licht_spiegelschrank_energie')
ORDER BY start_ts DESC
LIMIT 500;
Fazit
Insgesamt eine tolle Möglichkeit, Home Assistant Statistiken zu korrigieren oder leere Zwischenräume aufzufüllen, sollte es doch mal zu Falschmeldungen von Sensoren kommen.
Wenn du Fragen oder Anmerkungen hast, zögere nicht, sie mir unten in den Kommentaren mitzuteilen und ich werde mein Bestes tun, um dir zu helfen. Vielen Dank fürs Zuschauen!



Danke gleich mal mein Ausreißer gefixt
Immer überlegt ob das geht und dann machst du ein Video dazu, top! Leider sehe ich den Fehler im Energiedashboard kann aber den Sensor nicht finden der den Fehler beinhaltet. Hat jemand einen Rat?
Ich denke ein wichtiger Punkt ist auch das Vermeiden falscher Werte in dem man SML Stromzähler mit Home Assistant auslesen (lokal) - PowerFox Alternative und anderswo Sensoren so gestaltet das nicht verfügbare Messfühler oder welche die 0 Werte liefern abfängt. Damit vermeidet man das Ausreißer entstehen. Eventuell wäre ein Verweis auf Fehlersuche und Lösen des eigentlichen Problems hier gut.
Hallo!
Ich würde gerne falsche Statistikdaten korrigieren, habe aber das Problem, dass bei mir im Statistik-Bereich der Entwicklungswerkzeuge nur bei einem meiner Sensoren die Schaltfläche für “Adjust a statistic” vorhanden ist. Diesen möchte ich aber nicht ändern. Bei allen anderen Sensoren in meinem Home-Assistant fehlt diese Schaltfläche.
Hier ein Screenshot:
Kann mir jemand erklären woran das liegt und wie ich das ändern kann, damit ich die Statistik eines Luftfeuchtigkeitssensors (nicht im Screenshot) ändern kann?
Home-Assistant läuft bei mir auf einem Raspberry Pi 4 und alle Updates sind durchgeführt.
Hallo Simon,
Danke für Deine hilfreichen Anleitungen. Homeassistant hat es mittlerweile vereinfacht Ausreisser zu finden und zu korrigieren. Dennoch funktioniert das bei mir nicht. Wenn ich in der Statistik alle wesentlichen Ausreisser gefunden und eleminiert habe, dann sind sie dort dauerhaft verschwunden. Aber in meiner anzeigenden Übersicht sind die falschen Werte immer noch vorhanden. Was muss ich noch machen das die falschen Werte verschwinden. Ich habe die SQL Datenbank.
Jede fehlende notwendige Information zur Lösung reiche ich dann nach.
Vielen Dank vorab!