Daten aus der SQLITE-DB löschen - falsche Werte

Hallo,
ich verzweifle gerade an der Aufgabe Ausreisser meiner Entität sensor.vu_strom_power_in aus de DB zu löschen.
Die Entität misst über einen HICHI die Stromaufnahme in W und speichert sie in der DB. Aufgrund eines Netzwerkproblems habe ich 3 Ausreißer, wo der Wert von sensor.vu_strom_power_in 999.999 W ist.
Ich habe nun lange im Netz gesucht und gedacht ich hätte die Lösung gefunden.

  1. ha core stop
  2. sqlite3 /config/home-assistant_v2.db
  3. Ich lasse mir die Ausreißer grösser 20000 in der Kurz- und Lang anzeigen.

Langzeit:

SELECT start, mean, max, min
FROM statistics
WHERE metadata_id = (
  SELECT id FROM statistics_meta
  WHERE statistic_id = 'sensor.vu_strom_power_in'
)
AND max > 20000;

Kurzzeitdaten:

SELECT start, mean, max
FROM statistics_short_term
WHERE metadata_id = (
  SELECT id FROM statistics_meta
  WHERE statistic_id = 'sensor.vu_strom_power_in'
)
AND max > 20000;
  1. Ich lösche die Daten:
    Langzeit löschen:

DELETE FROM statistics
WHERE metadata_id = (
  SELECT id FROM statistics_meta
  WHERE statistic_id = 'sensor.vu_strom_power_in'
)
AND max > 20000;

Kurzzeit löschen:

DELETE FROM statistics_short_term
WHERE metadata_id = (
  SELECT id FROM statistics_meta
  WHERE statistic_id = 'sensor.vu_strom_power_in'
)
AND max > 20000;
  1. Kontrolle wir Punkt 3 ob die Daten weg sind

  2. Dann noch ein DB aufräumen mit
    VACUUM;

ABER, die Daten werden in der History immer noch angezeigt ?!

Ich kann Dir zu Deinen Versuchen direkt in der HA DB etwas zu ändern nichts sagen und ich selber habe auch schon ewig keine Ausreißer mehr bei HA bearbeitet, aber eigentlich gibt es bei HA dafür das:


Aber wie schon gesagt habe ich das auch schon lange nicht mehr benutzt. :slightly_smiling_face:

VG Jim

Ich hänge mich mal an, ich habe auch das Problem mit (leider mehr Ausreißer) habe schonmal begonnen sie manuell (über Statistik –> Ausreißer) anzupassen, allerdings sind es sehr viele Werte da mein Reed Sensor vermutlich geprellt hatte.

Zum Aufbau:

Reed Sensor an ESP (sensor.esp32_temperature_gaszaehler_m3; jetzt mit Entprellung ;-)) –> liefert m³ an HA –> in config einen Sensor (sensor.gesamt_gasverbrauch_kwh) der in kWh umrechnet angelegt.

Im Energie Dashboard habe nun Ausreißer.

In meiner Influx DB finde ich die Werte, aber ich schaffe es nicht die letzten 48h zu löschen, chatgpt dreht sich auch im kreis und kann mir nicht wirklich helfen…

Update:
konnte einen Befehl “finden” der funktioniert hat:

USE “home_assistant”;
DELETE FROM “Wh” WHERE (“friendly_name”=‘gesamt_gasverbrauch_kwh’)
AND time >= 2026-03-28T11:00:00Z AND time <= 2026-03-30T11:00:00Z

:crayon:by HarryP:
. Zusammenführung Doppelpost (bei Änderungen oder hinzufügen von Inhalten bitte die „Bearbeitungsfunktion“ anstatt „Antworten“ zu nutzen)
. Code-/Logzeilen formatiert (bitte immer in </> einbinden)
. s.a.: (Neues Update & Features - Hier in der Community 🫶)

Zum Thema passend, vielleicht auch ergänzend, Auszüge aus meinen heutigen Diskussion mit Claude. Vorab: Mein Problem war, dass einen meiner 16 Temperatursensoren an der PV-Batterie gesponnen hat (Werte über 80 Grad). Dies war zum Glück Blödsinn. Dies nur kurz zur Erläuterung warum ich nach Werten über 70 Grad gesucht habe.

Meine Frage (erst mal vorsichtig vortasten):
In welchen Tabellen (standard SQlite) werden Sensorwerte angelegt? Eigentlich müssten es doch 3 Tabellen sein. Kurzzeitgedächnis, 5 Min. Aggregation und Langzeitspeicher (1 Std. Aggregation).

Antwort KI:
Deine Intuition ist im Kern richtig, aber es sind genau genommen zwei getrennte Systeme mit insgesamt mehr als drei Tabellen. Der entscheidende Punkt: Nur zwei davon sind wirklich „aggregiert" – das „Kurzzeitgedächtnis" ist es nicht.

1. Die Rohdaten (History) – nicht aggregiert

Das ist dein „Kurzzeitgedächtnis". Hier landet jeder einzelne State-Change genau so, wie er passiert ist – keine Mittelung, kein Min/Max. Beteiligte Tabellen: Home Assistant

  • states – die eigentlichen Zustandswerte (mit metadata_id, last_updated_ts usw.)

  • states_meta – Mapping von entity_id → metadata_id (spart Speicher, da die lange entity_id nicht in jeder Zeile steht)

  • state_attributes – die Attribut-JSONs, dedupliziert

Diese Tabelle wird nach purge_keep_days (Standard 10 Tage) automatisch bereinigt.

2. Die Statistik (Long-Term Statistics) – aggregiert

Hier sitzen deine beiden Aggregations-Stufen:

  • statistics_short_term – die 5-Minuten-Aggregate, berechnet aus der states-Tabelle. Wird ebenfalls nach purge_keep_days (Standard 10 Tage) gepurgt.

  • statistics – die 1-Stunden-Aggregate (Langzeit). Ein stündlicher Aggregat der Short-Term-Statistik wird gespeichert, und diese Tabelle wird nie automatisch gelöscht. Home AssistantHome Assistant

  • statistics_meta – wieder das Metadaten-Mapping für die Statistik-Einträge.

Der Datenfluss ist also gestaffelt: State-Changes werden in der states-Tabelle aufgezeichnet, alle 5 Minuten schreibt die Statistik-Kompilierung nach statistics_short_term, und alle 60 Minuten werden die Short-Term-Werte zu statistics aggregiert. GitHub

Kleine, aber wichtige Korrektur zu deinem Modell

Du hattest gesagt „Kurzzeitgedächtnis / 5-Min-Aggregation / Langzeit (1 Std)". Die Feinheit: Die states-Tabelle ist keine Aggregation – sie ist die vollständige, ungefilterte Rohaufzeichnung. Nur statistics_short_term (5 Min) und statistics (1 Std) sind aggregiert. Die 5-Minuten-Statistik zieht ihre Werte übrigens aus states, nicht umgekehrt.

Ein weiterer Aspekt: Für Statistik-Tabellen werden je nach state_class unterschiedliche Werte gespeichert – bei measurement sind das mean/min/max, bei total/total_increasing dagegen sum und ggf. last_reset_ts.

Nächste Frage (Ok, jetzt mal konkret werden):
Wie lautet der SQL-Befehl wenn ich aus der States-Tabelle für den Sensor “sensor.bat_temp_zelle13” alle Temperaturwerte > 70 Grad löschen möchte?

Hier ist der Befehl – aber ein wichtiger Punkt vorweg: In der aktuellen HA-Schema-Version steht die entity_id nicht mehr direkt in der states-Tabelle. Sie liegt ausgelagert in states_meta und wird über metadata_id verknüpft. Du brauchst also einen Subquery. Außerdem ist die Spalte state ein Text-Feld, weshalb du für den Zahlenvergleich casten musst.

Zuerst prüfen (immer empfehlenswert), was getroffen wird:

SELECT COUNT(*)
FROM states
WHERE metadata_id = (
    SELECT metadata_id FROM states_meta
    WHERE entity_id = 'sensor.bat_temp_zelle13'
)
AND CAST(state AS REAL) > 70;

Dann das eigentliche Löschen:

DELETE FROM states
WHERE metadata_id = (
    SELECT metadata_id FROM states_meta
    WHERE entity_id = 'sensor.bat_temp_zelle13'
)
AND CAST(state AS REAL) > 70;

Warum das so aussieht:

  • CAST(state AS REAL) > 70 wandelt den Text in eine Fließkommazahl um. Praktischer Nebeneffekt: Werte wie unavailable oder unknown ergeben beim Cast in SQLite 0.0 und werden dadurch automatisch nicht mitgelöscht.

  • Der Subquery holt sich die passende metadata_id. Wenn du unsicher bist, ob der Sensor evtl. unter mehreren metadata_ids geführt wird (z.B. nach Umbenennung), ersetze = durch IN und lass das SELECT als Liste laufen.

Unbedingt beachten:

  • Das löscht die Werte nur aus states (deinem „Kurzzeitgedächtnis"). Die 5-Minuten- und Stunden-Aggregate in statistics_short_term bzw. statistics bleiben unberührt. Die fehlerhaften 70°C-Ausreißer haben dort ggf. schon die max- oder mean-Werte verfälscht – die musst du separat über Entwicklerwerkzeuge → Statistiken oder direktes SQL auf die Statistik-Tabellen korrigieren.

Wenn du willst, kann ich dir auch die passenden Queries für die beiden Statistik-Tabellen schreiben.

Nächste Frage (man kennt sich nun und kann persönlicher werden):
Spann mich nicht auf die Folter, zeig schon.

Hier sind die passenden Queries. Wichtiger Unterschied vorweg: Die Statistik-Metatabelle ist anders aufgebaut als states_meta. Dort heißt die Spalte mit dem Sensornamen statistic_id (nicht entity_id), und der Primärschlüssel ist id (nicht metadata_id). Wenn du das aus dem states-Query 1:1 übernimmst, findet er nichts.

statistics_short_term (5-Minuten-Aggregate)

Erst prüfen:

SELECT COUNT(*)
FROM statistics_short_term
WHERE metadata_id = (
    SELECT id FROM statistics_meta
    WHERE statistic_id = 'sensor.bat_temp_zelle13'
)
AND max > 70;

Dann löschen:

DELETE FROM statistics_short_term
WHERE metadata_id = (
    SELECT id FROM statistics_meta
    WHERE statistic_id = 'sensor.bat_temp_zelle13'
)
AND max > 70;

statistics (1-Stunden-Aggregate / Langzeit)

DELETE FROM statistics
WHERE metadata_id = (
    SELECT id FROM statistics_meta
    WHERE statistic_id = 'sensor.bat_temp_zelle13'
)
AND max > 70;

Warum max > 70 und nicht state:

Ein Temperatursensor hat state_class: measurement, also stehen hier mean, min und max – kein einzelner Messwert. Die Spalten state und sum sind nur für total/total_increasing-Sensoren gefüllt und bei dir NULL. max > 70 erwischt zuverlässig jede Periode, in der irgendein Wert über 70 lag – auch wenn mean durch den Ausreißer nur leicht angehoben wurde. Würdest du auf mean > 70 filtern, würdest du kurze Spikes übersehen.

Der unvermeidbare Haken bei aggregierten Daten:

Anders als in states kannst du hier den Ausreißer nicht chirurgisch entfernen. Du löschst immer die ganze Periode. Lag in demselben 5-Minuten- bzw. 1-Stunden-Fenster auch ein legitimer Wert (z.B. echte 45°C), verschwindet der mit. Bei einem klaren Fehler (Sensor spuckt kurz 999°C aus) ist das meist verschmerzbar, aber du solltest es wissen.

Zwei weitere Punkte:

  • Home Assistant regeneriert gelöschte Statistik-Perioden nicht automatisch aus states neu – es entstehen also Lücken in den Langzeit-Charts. Das ist normalerweise gewollt (Ausreißer weg), aber erwartbar.

  • Wenn du die betroffenen Zeitpunkte kennst, kannst du zusätzlich zeitlich eingrenzen, um versehentliche Treffer zu vermeiden, z.B. AND start_ts BETWEEN 1700000000 AND 1700086400 (Unix-Timestamps).