At the moment I've got an sqlite3 database that keeps track of the state of my smart home devices. The relevant parts of the schema for the main table are
CREATE TABLE states(
state_id INTEGER NOT NULL,
entity_id VARCHAR(255),
state VARCHAR(255),
last_updated DATETIME
);
I'm trying to calculate how long each entity has been in the state "on" for each day. Currently my thought would be to use the lead window function to create a column with the next updated time:
CREATE VIEW states_with_next_update AS
SELECT *, lead(last_updated,1) over (PARTITION BY entity_id) as next_update
FROM states;
and then it would be possible to subtract the next updated time from the current time to get the total time each entity was in a certain state for.
CREATE VIEW states_with_durations AS
SELECT *, julianday(next_update) - julianday(last_updated) as state_duration, date(last_updated) as day
FROM states_with_next_update;
With the duration of each state I can now use aggregate functions to calculate the total time each was in the "on" state:
SELECT day, entity_id, sum(state_duration)
FROM state_with_durations
WHERE state = "on"
GROUP BY day, entity_id;
The only problem with this method is that next_update
may not fall in the same day leading to durations
that contain time from two (or more) consecutive days, which leads to over counting on the first day, and under counting on the subsequent.
For example if an entity is in the state "on" from 2022-11-10 20:00 to 2022-11-11 02:00, the total for 2022-11-10 would read 6, and the total for 2020-11-11 would read 0.
So the question is, how do I make it so that in the example above the sum for the "on" state reads 4 hours for the day 2022-11-10, and 2 hours for 2022-11-11?