Of course, what we are emulating here is called a "Process Historian", common
examples being PHD and PI. So, if you make a few minor adjustments, you can
make this run just about as fast as a "designed for purpose" Process Historian.
The changes are that you need to store the data in an "economical format". I
have chosen to store the timestamp as a floating-point julianday number. You
also need to calculate and store the slope to the previous engineering value
each time you store a value. You must also insert the data in chronological
order and you may not update a value once it has been inserted.
This is about 500 times (or more) faster than using the table you created. The
following work the same as the previous example but uses triggers to enforce
the constraints and calculate the slope for new engineering values stored. And
you only need to change the '+1 day' to whatever interval you want to use.
This will load the data into the pwr table from your existing table.
drop table pwr;
create table pwr
(
timestamp float primary key,
reading float not null,
ratetoprior float
) without rowid;
create trigger pwr_ins_stamp before insert on pwr
begin
select raise(ABORT, 'Data insertion must be in chronological order')
where new.timestamp < (select max(timestamp) from pwr);
end;
create trigger pwr_ins_slope after insert on pwr
begin
update pwr
set ratetoprior = (new.reading - (select reading
from pwr
where timestamp < new.timestamp
order by timestamp desc
limit 1))
/
(new.timestamp - (select timestamp
from pwr
where timestamp < new.timestamp
order by timestamp desc
limit 1))
where timestamp = new.timestamp;
end;
create trigger pwr_upd_error after update of timestamp, reading on pwr
begin
select raise(ABORT, 'Data update prohibited');
end;
insert into pwr (timestamp, reading)
select julianday(timestamp),
total_kwh
from power
order by julianday(timestamp);
select datetime(timestamp),
kwh
from (
with periods (timestamp) as
(
select julianday(date(min(timestamp), '-1 day') || ' 23:59:59.999')
from pwr
union all
select julianday(datetime(timestamp, '+1 day'))
from periods
where timestamp < (select max(timestamp) from pwr)
),
readings (timestamp, reading) as
(
select timestamp,
(select reading - (b.timestamp - p.timestamp) * ratetoprior
from pwr as b
where b.timestamp >= p.timestamp
limit 1) as reading
from periods as p
where timestamp between (select min(timestamp) from pwr)
and (select max(timestamp) from pwr)
)
select timestamp,
reading - lag(reading) over () as kwh
from readings
)
where kwh is not null;
--
The fact that there's a Highway to Hell but only a Stairway to Heaven says a
lot about anticipated traffic volume.
_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users