I got a basic one for the duration except for the last bit from 'ON' to 'NOW()'. It looks like this:
SELECT SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND, S1.datetime, S2.datetime))) AS duration
FROM Stack AS S1,
Stack AS S2
WHERE S1.id + 1 = S2.id AND
S1.status = 'ON'
This can probably be written as a JOIN as well, most people prefer that, but that's equivalent to this. There's a bit of juggling with the times, as you can see. The result is:
06:30:00
I spotted an error in your database, there are two id's with the value 7. I changed the second one to 8 and now the result is:
04:30:00
That cannot be right. Haha... sorry, let me think. OK, checked it, and it is correct. The 06:30:00 was caused by the error in the database.
The next query will compute the remaining time at the end of the database table:
SELECT SEC_TO_TIME(TIMESTAMPDIFF(SECOND, `datetime`, NOW())) AS `duration`
FROM `Stack`
WHERE `id` = (SELECT MAX(`id`) FROM `Stack`) AND
`status` = 'ON'
It now return the ridiculous:
838:59:59
This is not the right result, so ignore it. The date is simply too far back in the past for this query to work. To get a reasonable result from the database I changed all the dates from 2020-01-01 to 2021-01-22.
Finally we need to combine these two. And that's relatively simple:
SELECT
SEC_TO_TIME(
(SELECT SUM(TIMESTAMPDIFF(SECOND, S1.datetime, S2.datetime)) AS duration
FROM Stack AS S1,
Stack AS S2
WHERE S1.id + 1 = S2.id AND
S1.status = 'ON')
+
(SELECT TIMESTAMPDIFF(SECOND, `datetime`, NOW()) AS `duration`
FROM `Stack`
WHERE `id` = (SELECT MAX(`id`) FROM `Stack`) AND
`status` = 'ON')
);
And that should do it. Now I am sure there must be a better way to do this, but hey, it works!
Oh, if the last status is 'OFF' it results NULL. Let me work on that. This should do something:
SELECT
SEC_TO_TIME(CAST(
(SELECT SUM(TIMESTAMPDIFF(SECOND, `S1`.`datetime`, `S2`.`datetime`)) AS duration
FROM Stack AS `S1`,
Stack AS `S2`
WHERE `S1`.`id` + 1 = `S2`.`id` AND
`S1`.`status` LIKE 'ON')
+
IFNULL((SELECT TIMESTAMPDIFF(SECOND, `datetime`, NOW()) AS `duration`
FROM `Stack`
WHERE `id` = (SELECT MAX(`id`) FROM `Stack`) AND
`status` LIKE 'ON'), 0)
AS UNSIGNED));
I added the CAST(.... AS UNSIGNED) to remove the anything after the second.