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; -- 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 Keith Medcalf >Sent: Monday, 13 January, 2020 17:04 >To: SQLite mailing list <sqlite-users@mailinglists.sqlite.org> >Subject: Re: [sqlite] Capturing the changes in columns in a table > > >Note this only requires that "idate" be a unique orderable sequence >within "a" in order to work. It does not have to be particular (such as >a date/datetime). >It can be a date, a datetime, an integer (as in unixtime), a real (as in >julianday number), or any old sequence number and it will still work >exactly the same. > >Replace UNION with UNION ALL and add an ORDER BY clause at the end which >may help performance depending on the amount of data. > >create unique index i on t (a, idate) to optimize retrieval. > >-- >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 Keith Medcalf >>Sent: Monday, 13 January, 2020 16:51 >>To: SQLite mailing list <sqlite-users@mailinglists.sqlite.org> >>Subject: Re: [sqlite] Capturing the changes in columns in a table >> >> >>create table t (n INTEGER PRIMARY KEY, a, b, c, d, e, idate); >>insert into t (a, b, c, d, e, idate) values ('p001', 1, 2, 'n', 4, >'2019- >>02-11'); >>insert into t (a, b, c, d, e, idate) values ('p002', 2, 2, 'n', 4, >'2019- >>02-11'); >>insert into t (a, b, c, d, e, idate) values ('p003', 3, 2, 'n', 4, >'2019- >>02-11'); >>insert into t (a, b, c, d, e, idate) values ('p004', 4, 2, 'y', 4, >'2019- >>02-11'); >>insert into t (a, b, c, d, e, idate) values ('p005', 5, 2, 'y', 4, >'2019- >>02-11'); >>insert into t (a, b, c, d, e, idate) values ('p001', 10, 2, 'n', 4, >>'2019-02-12'); >>insert into t (a, b, c, d, e, idate) values ('p002', 2, 4, 'n', 4, >'2019- >>02-12'); >>insert into t (a, b, c, d, e, idate) values ('p003', 3, 2, 'y', 4, >'2019- >>02-12'); >>insert into t (a, b, c, d, e, idate) values ('p004', 4, 2, 'y', 4, >'2019- >>02-12'); >>insert into t (a, b, c, d, e, idate) values ('p005', 5, 2, 'y', 4, >'2019- >>02-12'); >>insert into t (a, b, c, d, e, idate) values ('p001', 10, 2, 'n', 4, >>'2019-02-13'); >>insert into t (a, b, c, d, e, idate) values ('p002', 2, 4, 'n', 4, >'2019- >>02-13'); >>insert into t (a, b, c, d, e, idate) values ('p003', 3, 2, 'y', 4, >'2019- >>02-13'); >>insert into t (a, b, c, d, e, idate) values ('p004', 5, 3, 'n', 4, >'2019- >>02-13'); >>insert into t (a, b, c, d, e, idate) values ('p005', 5, 3, 'y', 8, >'2019- >>02-13'); >> >> select * >> from ( >> select a, >> idate, >> 'b' as variable, >> lag(b, 1) over (partition by a order by idate) as oldv, >> b as newv >> from t >> union >> select a, >> idate, >> 'c' as variable, >> lag(c, 1) over (partition by a order by idate) as oldv, >> c as newv >> from t >> union >> select a, >> idate, >> 'd' as variable, >> lag(d, 1) over (partition by a order by idate) as oldv, >> d as newv >> from t >> union >> select a, >> idate, >> 'e' as variable, >> lag(e, 1) over (partition by a order by idate) as oldv, >> e as newv >> from t >> ) >> where oldv <> newv; >> >>a idate variable oldv newv >>---------- ---------- ---------- ---------- ---------- >>p001 2019-02-12 b 1 10 >>p002 2019-02-12 c 2 4 >>p003 2019-02-12 d n y >>p004 2019-02-13 b 4 5 >>p004 2019-02-13 c 2 3 >>p004 2019-02-13 d y n >>p005 2019-02-13 c 2 3 >>p005 2019-02-13 e 4 8 >> >>Change "<>" to "IS NOT" to find out when their was no previous value >> >>-- >>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: Monday, 13 January, 2020 12:42 >>>To: SQLite mailing list <sqlite-users@mailinglists.sqlite.org> >>>Subject: [sqlite] Capturing the changes in columns in a table >>> >>> >>>Greetings! >>> >>>Please observe the following, >>> >>> >>>create table t (n INTEGER PRIMARY KEY, a, b, c, d, e, idate); >>> >>>insert into t (a, b, c, d, e, idate) values ('p001', 1, 2, 'n', 4, >>'2019- >>>02-11'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p002', 2, 2, 'n', 4, >>'2019- >>>02-11'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p003', 3, 2, 'n', 4, >>'2019- >>>02-11'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p004', 4, 2, 'y', 4, >>'2019- >>>02-11'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p005', 5, 2, 'y', 4, >>'2019- >>>02-11'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p001', 10, 2, 'n', 4, >>>'2019-02-12'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p002', 2, 4, 'n', 4, >>'2019- >>>02-12'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p003', 3, 2, 'y', 4, >>'2019- >>>02-12'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p004', 4, 2, 'y', 4, >>'2019- >>>02-12'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p005', 5, 2, 'y', 4, >>'2019- >>>02-12'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p001', 10, 2, 'n', 4, >>>'2019-02-13'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p002', 2, 4, 'n', 4, >>'2019- >>>02-13'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p003', 3, 2, 'y', 4, >>'2019- >>>02-13'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p004', 5, 3, 'n', 4, >>'2019- >>>02-13'); >>> >>>insert into t (a, b, c, d, e, idate) values ('p005', 5, 3, 'y', 8, >>'2019- >>>02-13'); >>> >>> >>>The SQL below provide info only for two dates (2019-02-11 and 2019-02- >>>12): >>> >>> >>>select new.a,old.b,new.b, 'column b changed on ' || new.idate as info >>>from t as new >>> >>> LEFT JOIN t as old ON >>> >>> new.idate = '2019-02-12' >>> >>>AND old.idate = '2019-02-11' >>> >>>AND new.a = old.a >>> >>>WHERE >>> >>> new.b != old.b >>> >>>UNION ALL >>> >>>select new.a,old.c,new.c, 'column c changed on ' || new.idate as info >>>from t as new >>> >>> LEFT JOIN t as old ON >>> >>> new.idate = '2019-02-12' >>> >>>AND old.idate = '2019-02-11' >>> >>>AND new.a = old.a >>> >>>WHERE >>> >>> new.c != old.c >>> >>>UNION ALL >>> >>>select new.a,old.d,new.d, 'column d changed on ' || new.idate from t as >>>new >>> >>> LEFT JOIN t as old ON >>> >>> new.idate = '2019-02-12' >>> >>>AND old.idate = '2019-02-11' >>> >>>AND new.a = old.a >>> >>>WHERE >>> >>> new.d != old.d >>> >>>UNION ALL >>> >>>select new.a,old.e,new.e, 'column e changed on ' || new.idate from t as >>>new >>> >>> LEFT JOIN t as old ON >>> >>> new.idate = '2019-02-12' >>> >>>AND old.idate = '2019-02-11' >>> >>>AND new.a = old.a >>> >>>WHERE >>> >>> new.e != old.e >>> >>>ORDER by new.a; >>> >>> >>>p001|1|10|column b changed on 2019-02-12 >>>p002|2|4|column c changed on 2019-02-12 >>>p003|n|y|column d changed on 2019-02-12 >>>sqlite> >>> >>>What I would like is to cover all of the dates in the same command, so >>>that the output is this, >>> >>>p001|1|10|column b changed on 2019-02-12 >>>p002|2|4|column c changed on 2019-02-12 >>>p003|n|y|column d changed on 2019-02-12 >>>p004|4|5|column b changed on 2019-02-13 >>>p004|2|3|column c changed on 2019-02-13 >>>p004|y|n|column d changed on 2019-02-13 >>>p005|2|3|column c changed on 2019-02-13 >>>p005|4|8|column e changed on 2019-02-13 >>> >>>Yes, I know I can get all the dates and build the SQL as I did above, >>but >>>is there a way to do this in one call? Thanks for the help. >>> >>>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 > > > >_______________________________________________ >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