HA - SQLite Insights: Datenbank-Layout / Beispiel-SQL-Queries

Um bessere SQL-Abfragen zusammenstellen zu können, habe ich mir das Datenbankschema von Home-Assistant nĂ€her angesehen. ZunĂ€chst hauptsĂ€chlich um bestimmte historische Daten zu korrigieren, spĂ€ter um die Energievorhersage meiner PV-Anlage zu verbessern, was eine effizientere Steuerung der Heizung ermöglicht. Details zu den Abfragen fĂŒr die PV-Prognose folgen in einem gesonderten Artikel..

Mittels SQL-Query können direkte Abfragen oder Änderungen an der Datenbank vorgenommen werden:

Siehe auch die unterschiedlichen Möglichkeiten fĂŒr einen direkten Zugriff auf dei Datenbank: 3 Varianten: SQLite Datenbank Zugriff - Home Assistant.

Ein Blick in SQLite3 Editor in VSCode, zeigt die einzelnen Tabellen und deren Beziehungen.

Interessant fĂŒr aktuelle Daten innerhalb von 10 Tagen ist die Tabelle "states". Die Tabelle "statistics" liefert auch Ă€ltere Daten: Pro Stunde einen Wert. 

  Tabellenname Zweck
States (alle aktuellen Statusinformationen: bis 10 Tage) states_meta Liste aller EntitÀten: 
Eindeutige Kennung (entity_id), Beispiel sensor.temperatur und die zugehörige interne Datenbank-id in Form einer fortlaufenden Nummer (metadata_id). Die Tabelle ĂŒbersetzt die metadata_id auf die entity_id
states Alle Statusinformationen aller EntitÀten: Verwendet die id aus states_meta.
Statistik und LTS / Langzeitstatistik statistics_meta

Liste aller EntitÀten mit Statistikdaten: id zu entity_id (z.B. sensor.temperatur).
Die in statistic_meta verwendete id ist nicht gleich der id in states_meta: Die Statistik-Tabellen fĂŒhren eine eigene interne Datenbank-id.

statistics

Alle LTS-Statusinformationen (Pro Stunde ein Wert, gespeichert auch lÀnger als 10 Tage). Verwendet die id aus statistics_meta.

Handelt es sich bei dem Sensor nicht um einen fortlaufenden ZĂ€hler, sondern einen ZĂ€hler vom Typ Messung (Eigenschaft: state_class=measurement), wird neben dem Durchschnittswert auch ein Maximal und Minimal-Wert gespeichert.

statistiscs_short_term

Statusinformationen der letzten 10 Tage im 5-Minutentakt. Verwendet die id aus statistics_meta.

Handelt es sich bei dem Sensor nicht um einen fortlaufenden ZĂ€hler, sondern einen ZĂ€hler vom Typ Messung (Eigenschaft: state_class=measurement), wird neben dem Durchschnittswert auch ein Maximal und Minimal-Wert gespeichert.

States- Daten (aktuelle Werte aller EntitÀten)

Die eindeutigen Kennungen (entity_id) aller EntitÀten sind in der Tabelle "states_meta" gelistet:

id metadata_id entity_id
1 20 sensor.pv_spannung_dc
2 21 sensor.pv_strom_dc
3 22 sensor.pv_leistung_ac

Die eigentlichen Werte der EntitÀten werden in der Tabelle "states" gespeichert, darin unter Verwendung der metadata_id:

state_id state last_changed_ts last_reported_ts last_updated_ts attributes_id metadata_id
1 800.00 1743775748.382725 1743775743.2130053 1743775743.2130053 1 20
2 810.00 1743775848.382725 1743775843.2130053 1743775843.2130053 2 20
3 799.10 1743775948.382725 1743775943.2130053 1743775943.2130053 3 20

Die gelisteten Werte in diesem Beispiel gehören also alle zu "sensor.pv_spannung_dc", da die metadata_id "20" verwendet wird und diese in states_meta auf "sensor.pv_spannung_dc" ĂŒbersetzt wird. Die attributes_id verweist auf einen zusĂ€tzlichen Eintrag in der Tabelle "state_attributes". Über eine angepasste SQL-Abfrage können die Daten der 3 Tabelle zusammengefasst und in einem lesbaren Format ausgegeben werden:

Letzte Stunde, alle Status - Daten aller EntitÀten inklusive entity_id und shared_attrs: 

Folgende Query listet sÀmtliche Statusinformationen aller EntitÀten der letzten Stunde:

SELECT STRFTIME('%Y.%m.%d %H:%M', datetime(last_updated_ts, 'unixepoch', 'localtime')) AS date,
    states_meta.entity_id,
    states.state,
    shared_attrs
FROM states
INNER JOIN states_meta ON states_meta.metadata_id = states.metadata_id
INNER JOIN state_attributes ON state_attributes.attributes_id = states.attributes_id
WHERE last_updated_ts BETWEEN strftime('%s', 'now', '-1 hour') AND strftime('%s', 'now')

Aktueller Status fĂŒr eine bestimmte EntitĂ€t

SQL-Query:

select datetime(last_updated_ts, 'unixepoch', 'localtime') AS readabledate,state from states where metadata_id = ( SELECT metadata_id FROM states_meta
WHERE entity_id = 'sensor.flowmeter_sum')  order by last_updated_ts desc limit 10;

Ausgabe:

readabledate state
2025-04-04 14:17:38 5812.24
2025-04-04 14:07:08 5812.23
2025-04-04 13:55:26 5812.22

Aktueller Status fĂŒr eine bestimmte EntitĂ€t inklusive shared_attrs

ZusĂ€tzlich zum aktuellen Status (state) besitzen bestimmte EntitĂ€ten zusĂ€tzliche Eigenschaften, abgelegt in einer zusĂ€tzlichen Spalte: shared_attrs. FĂŒr das Auslesen einer EntitĂ€t und deren zusĂ€tzlichen Eigenschaften (shated_attrs) kann die folgende Query verwendet werden:

SELECT STRFTIME('%Y.%m.%d %H:%M',datetime(last_updated_ts, 'unixepoch', 'localtime')) as readabledate,states_meta.entity_id,states.state,shared_attrs FROM states
INNER JOIN states_meta ON states_meta.metadata_id = states.metadata_id
INNER JOIN state_attributes ON state_attributes.attributes_id = states.attributes_id
WHERE states_meta.entity_id = 'sensor.fronius_storage_chast' order by last_updated_ts DESC limit 1

Ausgabe:

readabledate entity_id state shared_attrs
2025.04.04 13:38 sensor.fronius_storage_chast FULL {"integration":"sunspec","suns ...

Status einer bestimmten EntitÀt zu einem bestimmten Zeitpunkt, als Beispiel gestern zur selben Zeit

SQL-Query

SELECT STRFTIME('%Y.%m.%d %H:%M',datetime(last_updated_ts, 'unixepoch', 'localtime')) as date,states_meta.entity_id,states.state,shared_attrs FROM states
INNER JOIN states_meta ON states_meta.metadata_id = states.metadata_id
INNER JOIN state_attributes ON state_attributes.attributes_id = states.attributes_id
WHERE states_meta.entity_id = 'sensor.fronius_storage_chast' and 
last_updated_ts < (SELECT unixepoch(datetime('now'),'-1 days')) order by last_updated_ts DESC limit 1

Ausgabe:

date entity_id state shared_attrs
2025.04.03 12:46 sensor.fronius_storage_chast FULL {"integration":"sunspec","suns ...

EntitÀten mit zusÀtzlichen Daten in shared_attrs: z.B. Wetterdaten

Die folgende Abfrage ruft die letzten zehn DatensÀtze zur EntitÀt "weather.home" ab. Enthalten sind das formatierte Datum, die EntitÀts-ID, der Zustand und gemeinsame Attribute aus der shared_attrs- Tabelle. Die Ergebnisse wurden in folgender SQL-Abfrage nach dem letzten Aktualisierungszeitpunkt sortiert:

SELECT STRFTIME('%Y.%m.%d %H:%M',datetime(last_updated_ts, 'unixepoch', 'localtime')) as readabledate,states_meta.entity_id,states.state,shared_attrs FROM states
INNER JOIN states_meta ON states_meta.metadata_id = states.metadata_id
INNER JOIN state_attributes ON state_attributes.attributes_id = states.attributes_id
WHERE states_meta.entity_id like '%weather.home' and 
last_updated_ts < (SELECT unixepoch(datetime('now'),'-0 days')) order by last_updated_ts DESC limit 10

Ausgabe:

readabledate entity_id state shared_attrs
2025.04.04 13:38 weather.home sunny {"temperature":18.9,"dew_point":8.8,"temperature_unit":"°C","humidity":52,"cloud_coverage":0.0,"uv_index":3.2,"pressure":1017.7,"pressure_unit":"hPa","wind_bearing":61.7,"wind_speed":15.5,"wind_speed_unit":"km/h","visibility_unit":"km","precipitation_unit":"mm","friendly_name":"Forecast Home"}...
2025.04.04 13:27 weather.home sunny {"temperature":18.9,"dew_point":8.8,"temperature_unit":"°C","humidity":52,"cloud_coverage":0.0,"uv_index":3.2,"pressure":1017.7,"pressure_unit":"hPa","wind_bearing":61.7,"wind_speed":15.5,"wind_speed_unit":"km/h","visibility_unit":"km","precipitation_unit":"mm","friendly_name":"Forecast Home"}...
2025.04.04 12:26 weather.home sunny {"temperature":18.7,"dew_point":8.0,"temperature_unit":"°C","humidity":50,"cloud_coverage":0.0,"uv_index":4.0,"pressure":1018.5,"pressure_unit":"hPa","wind_bearing":63.1,"wind_speed":15.8,"wind_speed_unit":"km/h","visibility_unit":"km","precipitation_unit":"mm","friendly_name":"Forecast Home"}...

Um bestimmte Werte aus der Spalte shared_attrs als eigene Spalten anzuzeigen, können die JSON-Daten mit folgender SQL-Abfrage extrahiert werden: 

SELECT STRFTIME('%Y.%m.%d %H:%M',datetime(last_updated_ts, 'unixepoch', 'localtime')) as readabledate,states_meta.entity_id,states.state,json_extract(shared_attrs, '$.temperature') AS temperature,json_extract(shared_attrs, '$.cloud_coverage') AS cloud_coverage, shared_attrs FROM states
INNER JOIN states_meta ON states_meta.metadata_id = states.metadata_id
INNER JOIN state_attributes ON state_attributes.attributes_id = states.attributes_id
WHERE states_meta.entity_id like '%weather.home' and 
last_updated_ts < (SELECT unixepoch(datetime('now'),'-0 days')) order by last_updated_ts DESC limit 10

Ausgabe:

readabledate entity_id state temperature cloud_coverage shared_attrs
2025.04.04 13:38 weather.home sunny 18.9 0.0 {"temperature":18.9,"dew_point":8. ...
2025.04.04 13:27 weather.home sunny 18.9 0.0 {"temperature":18.9,"dew_point":8. ...
2025.04.04 12:26 weather.home sunny 18.7 0.0 {"temperature":18.7,"dew_point":8. ...

Historische Daten: Werte von den Statistik-Tabellen

Wie auch die Status-Tabelle verwenden die Statistik-Tabellen nicht direkt die eindeutige EntitĂ€ts-ID (z.B. sensor.temperatur), sondern eine Meta-Tabelle (statistics_meta) fĂŒr die Übersetzung der EintitĂ€ts-ID (Spalte: statistic_id) auf eine id (Nummer)

id statistic_id source unit_of_measurement has_mean has_sum name mean_type
1 sensor.openweathermap_temperature recorder °C NULL False NULL 1
30 sensor.displaykueche_power recorder W NULL False NULL 1
88 sensor.grid_consumption_energy recorder Wh NULL True NULL 0

Alternativ zur Status-Tabelle (states), können die Werte einer bestimmten EntitĂ€t ĂŒber eine SQL-Query aus der Tabelle "statistics" gelesen werden. Die metatdata_id wird auch hier ĂŒber eine Sub-Query aus der Tabelle statistics_meta ĂŒbersetzt:

Datenbank Query:

select datetime(created_ts, 'unixepoch', 'localtime') AS readabledate, * from statistics WHERE metadata_id = ( SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.flowmeter_sum') AND strftime('%Y%m%d',datetime(created_ts, 'unixepoch','localtime')) > strftime('%Y%m%d', datetime('now','localtime','-3 days'));

Ausgabe:

readabledate id mean min max state sum metadata_id created_ts start_ts
2025-04-03 00:00:10 6212270 NULL NULL NULL 5795.28 18346.070000000367 606 1743638410.8686857 1743634800.0
2025-04-03 01:00:10 6212828 NULL NULL NULL 5795.34 18346.13000000037 606 1743642010.2952905 1743638400.0
2025-04-03 02:00:10 6213384 NULL NULL NULL 5795.39 18346.18000000037 606 1743645610.320077 1743642000.0

Die Statistik-Tabelle hat eine weitere Besonderheit: AbhÀngig vom Sensor-Typ werden unterschiedliche Spalten der Datenbanktabelle verwendet: Sensoren des Typs state_class=total oder total_increasing speichern deren Werte in den Spalten: "state" und "sum". Ein Sensor des Typs "state_class = measurement" verwendet die Spalten mean, min und max.

Hier die eine SQL-Query fĂŒr einen Sensor des Typs: "state_class = measurement":

select datetime(created_ts, 'unixepoch', 'localtime') AS readabledate,* from statistics WHERE metadata_id = ( SELECT id FROM statistics_meta WHERE statistic_id = 'sensor.eg_temperatur') AND strftime('%Y%m%d',datetime(created_ts, 'unixepoch','localtime')) > strftime('%Y%m%d', datetime('now','localtime','-3 days'));

Ausgabe:

readabledate id created start mean min max state sum metadata_id created_ts start_ts
2025-04-03 00:00:10 6212150 NULL NULL 23.0 23.0 23.0 NULL NULL 319 1743638410.8686857 1743634800.0
2025-04-03 01:00:10 6212708 NULL NULL 23.0 23.0 23.0 NULL NULL 319 1743642010.2952905 1743638400.0
2025-04-03 02:00:10 6213264 NULL NULL 23.0 23.0

23.0

NULL NULL 319 1743645610.320077 1743642000.0

Die Tabelle "statistics" speichert stĂŒndliche Werte, ohne diese zu löschen. Anders die Tabelle statistics_short_term: diese speichert die Werte im 5-Minuten-Takt und löscht die Daten, wie auch die "states"-Tabelle nach 10 Tagen. Vom Datenbank-Layout ist die Tabelle statistics und statistics_short_term ident. Beide verwenden die Tabelle statistics_meta und beide befĂŒllen abhĂ€ngig vom Sensor-Typ state und sum oder mean, min und max.

Als Beispiel werden fĂŒr die Detailansicht eines Sensors fĂŒr: Minimum, Mittel und Maximum die Daten aus den Spalten "mean", "min" und "max" der Tabelle "statistics_short_term" verwendet:

 

Fazit

Das Home-Assistant Datenbankschema erlaubt eine effiziente Auswertung von EntitĂ€tsdaten durch die Verwendung von Tabellen fĂŒr aktuelle und historische Informationen. Die Tabelle "states" bietet Zugang zu aktuellen Daten, wĂ€hrend "statistics" fĂŒr Langzeitdaten mit stĂŒndlichem Intervall genutzt wird. EntitĂ€ten und ihre zusĂ€tzlichen Attribute können durch SQL-Abfragen zielgerichtet und individuell ausgewertet werden.

positive Bewertung({{pro_count}})
Beitrag bewerten:
{{percentage}} % positiv
negative Bewertung({{con_count}})

DANKE fĂŒr deine Bewertung!

Beitrag erstellt von Bernhard | Veröffentlicht: 22.04.2025 | Aktualisiert: 22.04.2025 | Translation English |🔔 | Kommentare:0

Fragen / Kommentare


 
Durch die weitere Nutzung der Seite stimmst du der Verwendung von Cookies zu Mehr Details