You should probably declare your table thusly:

create table werte
(
    minutestamp integer default (strftime('%s', 'now') / 60),
    ...
);
create index werte_minutestamp on werte (minutestamp);

then your "minutestamp" is in minutes since the Unix epoch and you can create 
an index on it.

(and assuming that you always collect data on or after the "turn of the minute" 
and before the next following "turn of the minute")

Finding all the "matching" records is as easy as:

select C.minutestamp as currentminute,
       C.value       as currentvalue,
       Y.minutestamp as yesterdayminute,
       Y.Value       as yesterdayvalue
  from werte as C
  join werte as Y
 where Y.minutestamp = C.minutestamp - 1440;

with appropriate constraints such as order and limit and/or other conditionals 
...

(for example to find the top minute and the predecessor day value, append 
"order by C.Minutestamp DESC limit 1" to the query.

Unless you happen to use the database at all times in a jurisdiction that is 
not subject to the political whims of the day fiddling with 'localtime', you 
want to store GMT/UT1 (often whimsically referred to as UTC) offsets in the 
database ... otherwise you will end up with "duplicated" stamps and "skipped" 
stamps on a periodic basis (once each per year for most jurisdictions, twice 
each per year for some jurisdictions, and three or more times a year for some 
others).  Of course, if you are running entirely and only on a platform for 
which the kernel localtime function uses proper tzdata translation (and those 
tables are kept up-to-date) then you are probably OK, except that none of the 
sqlite3 timestamp builtins record the offset from GMT/UT1, so unless you store 
only GMT/UT1 there is no way to actually know (or determine) the actual 
"instant time" ...

If you do need to take the political whims of localtime into account, then you 
will have to also store the "current political whim" flag along with the 
minutestamp and use it to modify the results ... (which can be a nightmare 
especially if you want to do it at the SQL level rather than the application 
level).

---
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.

>-----Original Message-----
>From: sqlite-users [mailto:sqlite-users-
>boun...@mailinglists.sqlite.org] On Behalf Of nitpi...@arcor.de
>Sent: Monday, 30 October, 2017 10:51
>To: SQLite mailing list
>Subject: Re: [sqlite] calculation with the result of two select
>results
>
>Hi Richard,
>
>I'm not sure, what You mean.
>My intention was to drop the seconds while finding the correct rows.
>The data
>for the records is collected by a perl script and this stores the
>records
>sometimes at hh:mm:09 sometimes at hh:mm:10.
>The timestamp is assigned automaticly while creating using the
>default...:
>sqlite> .schema
>CREATE TABLE "werte"(timestamp datetime default (datetime
>(current_timestamp, 'localtime')), ...
>
>A cronjob is starting a shellscript which is starting
>sqlite3 </home/.../daily_status.sql
>This happens always shortly after the beginning of a minute, so the
>risk
>that the both 'now' deliver different results is very low.
>
>Regards Matth
>
>Output of EXPLAIN:
>sqlite> .open /dev/shm/log.db
>sqlite> EXPLAIN SELECT (
>   ...> SELECT kwh_th FROM werte WHERE STRFTIME('%Y-%m-%d %H:%M',
>timestamp) = STRFTIME('%Y-%m-%d %H:%M', 'now', 'localtime', '-1
>minute')
>   ...> ) - (
>   ...> SELECT kwh_th FROM werte WHERE STRFTIME('%Y-%m-%d %H:%M',
>timestamp) = STRFTIME('%Y-%m-%d %H:%M', 'now', 'localtime', '-1
>days', '-1 minute')
>   ...> );
>0|Init|0|28|0||00|
>1|Once|0|13|0||00|
>2|Null|0|3|0||00|
>3|Integer|1|4|0||00|
>4|OpenRead|0|2|0|6|00|
>5|Rewind|0|12|0||00|
>6|Column|0|0|7||00|
>7|Function|1|6|5|strftime(-1)|02|
>8|Ne|8|11|5||51|
>9|Column|0|5|3||00|
>10|IfZero|4|12|-1||00|
>11|Next|0|6|0||01|
>12|Close|0|0|0||00|
>13|Once|1|25|0||00|
>14|Null|0|9|0||00|
>15|Integer|1|10|0||00|
>16|OpenRead|1|2|0|6|00|
>17|Rewind|1|24|0||00|
>18|Column|1|0|12||00|
>19|Function|1|11|5|strftime(-1)|02|
>20|Ne|13|23|5||51|
>21|Column|1|5|9||00|
>22|IfZero|10|24|-1||00|
>23|Next|1|18|0||01|
>24|Close|1|0|0||00|
>25|Subtract|9|3|1||00|
>26|ResultRow|1|1|0||00|
>27|Halt|0|0|0||00|
>28|Transaction|0|0|6|0|01|
>29|TableLock|0|2|0|werte|00|
>30|String8|0|6|0|%Y-%m-%d %H:%M|00|
>31|String8|0|14|0|%Y-%m-%d %H:%M|00|
>32|String8|0|15|0|now|00|
>33|String8|0|16|0|localtime|00|
>34|String8|0|17|0|-1 minute|00|
>35|Function|15|14|8|strftime(-1)|04|
>36|String8|0|11|0|%Y-%m-%d %H:%M|00|
>37|String8|0|18|0|%Y-%m-%d %H:%M|00|
>38|String8|0|19|0|now|00|
>39|String8|0|20|0|localtime|00|
>40|String8|0|21|0|-1 days|00|
>41|String8|0|22|0|-1 minute|00|
>42|Function|31|18|13|strftime(-1)|05|
>43|Goto|0|1|0||00|
>sqlite>
>
>On Monday, 30 October 2017 12:10:30 CET Richard Hipp wrote:
>> On 10/30/17, Wout Mertens <wout.mert...@gmail.com> wrote:
>> >> WHERE STRFTIME('%Y-%m-%d %H:%M', timestamp) = STRFTIME('%Y-%m-%d
>%H:%M',
>> >
>> > 'now', 'localtime', '-1 minute');
>> >
>> > Won't this run strftime on all rows? Unless you have a calculated
>index on
>> > that strftime function, I think you should convert the 'now' to a
>> > timestamp…
>> The first STRFTIME() does run for every row, because timestamp is
>> different for every row.  But the second STRFTIME() should be
>factored
>> out and run only once.  Please verify that this is happening by
>> looking at the output of EXPLAIN, and report the problem to me if
>you
>> find out otherwise.
>
>
>_______________________________________________
>sqlite-users mailing list
>sqlite-users@mailinglists.sqlite.org
>http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users



_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to