Assuming (a, idate) is indexed and unique, then give the following a whirl on 
your larger data.  It does the same thing but does not use window functions to 
find the prior value -- it does a correlated subquery instead.  I would expect 
that it is slower with real data than the window function version because it 
pushes the conditional into each union leg so that it does two correlated 
subqueries (one for the select and one for the where), but it might be 
interesting to see if it is actually slower.  The window function version 
generates a huge internal VDBE program, but all the "bits" are co-routines.

  select a,
         idate,
         variable,
         oldv,
         newv
    from (
            select a,
                   idate,
                   'b' as variable,
                   (select b
                      from t
                     where a == o.a
                       and idate < o.idate
                  order by idate desc
                     limit 1) as oldv,
                   b as newv
              from t as o
         union
            select a,
                   idate,
                   'c' as variable,
                   (select c
                      from t
                     where a == o.a
                       and idate < o.idate
                  order by idate desc
                     limit 1) as oldv,
                   c as newv
              from t as o
         union
            select a,
                   idate,
                   'd' as variable,
                    (select d
                       from t
                      where a == o.a
                        and idate < o.idate
                   order by idate desc
                      limit 1) as oldv,
                    d as newv
               from t as o
         union
             select a,
                    idate,
                    'e' as variable,
                    (select e
                       from t
                      where a == o.a
                        and idate < o.idate
                   order by idate desc
                      limit 1) as oldv,
                    e as newv
               from t as o
         )
   where oldv <> newv;



-- 
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 <sqlite-users-boun...@mailinglists.sqlite.org> On
>Behalf Of Jose Isaias Cabrera
>Sent: Tuesday, 14 January, 2020 06:19
>To: SQLite mailing list <sqlite-users@mailinglists.sqlite.org>
>Subject: Re: [sqlite] Capturing the changes in columns in a table
>
>
>
>Keith Medcalf, on Monday, January 13, 2020 08:03 PM, wrote...
>>
>>
>> And this version is several times faster since only the changes are
>> union'd which minimizes the total number of records processed.
>> The index should be "create index i on t (a, idate);" Because of the
>way
>> indexes work, entries on the same a, idate will be ordered by n.
>(though
>> really idate should be unique within a, so the index should be a unique
>> index)
>>
>>   select a, idate, variable, oldv, newv
>>     from (
>>           select a,
>>                  idate,
>>                  'b' as variable,
>>                  lag(b, 1) over (partition by a order by idate) as
>oldv,
>>                  b as newv
>>             from t
>>         order by a, idate
>>          )
>>    where oldv <> newv
>> union all
>>   select a, idate, variable, oldv, newv
>>     from (
>>           select a,
>>                  idate,
>>                  'c' as variable,
>>                  lag(c, 1) over (partition by a order by idate) as
>oldv,
>>                  c as newv
>>             from t
>>         order by a, idate
>>          )
>>    where oldv <> newv
>> union all
>>   select a, idate, variable, oldv, newv
>>     from (
>>           select a,
>>                  idate,
>>                  'd' as variable,
>>                  lag(d, 1) over (partition by a order by idate) as
>oldv,
>>                  d as newv
>>             from t
>>         order by a, idate
>>          )
>>    where oldv <> newv
>> union all
>>   select a, idate, variable, oldv, newv
>>     from (
>>           select a,
>>                  idate,
>>                  'e' as variable,
>>                  lag(e, 1) over (partition by a order by idate) as
>oldv,
>>                  e as newv
>>             from t
>>         order by a, idate
>>          )
>>    where oldv <> newv
>> order by a, idate, variable;
>>
>
>Wow!  Thanks, Keith.  Yes, this one is much faster.  As Ryan suggested, I
>will use this one. Thank so much. I really appreciate the help.  I
>already have an index on (a,idate).  I hope that I will be like you guys
>someday. ;-)  Thanks again.
>
>josé
>_______________________________________________
>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