On 2020/01/13 9:42 PM, Jose Isaias Cabrera wrote:
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');

...

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.


Of course there is :)

Many questions are not clear though.
I assumed you are only interested in day-on-day changes, because in many days there can be many different values, if you measure them all against the last day, it will look like many changes between day X and the last day, when really you are probably interested only in the change from one day to the next day.

I also assumed that the days you will give as the input, let's call that min date and max date of the report, will refer to the days on which changed happened - which seems obvious, but the query must change if it is not the case.

Anyway, here is the SQL to achieve it. I made 2 queries, one in which it just gets the min and max from your data, and the other in which you can specify the min and max date. I guess the second one will be more what you want - the nice t hing is your calling program only needs to adjust those two values once, nowhere else:

(PS: I left the whole generated output in so you can see at the bottom, those errors are not errors, but just informing us that SQLite is creating indexes for those CTE tables, which is great and means this should be relatively fast  on large datasets even.)


  -- SQLite version 3.30.1  [ Release: 2019-10-10 ]  on SQLitespeed version 2.1.3.11.

  -- Script Items: 4          Parameter Count: 0
  -- 2020-01-14 00:08:17.875  |  [Info]       Script Initialized, Started executing...   -- ================================================================================================

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')
,('p002', 2, 2, 'n', 4, '2019-02-11')
,('p003', 3, 2, 'n', 4, '2019-02-11')
,('p004', 4, 2, 'y', 4, '2019-02-11')
,('p005', 5, 2, 'y', 4, '2019-02-11')
,('p001',10, 2, 'n', 4, '2019-02-12')
,('p002', 2, 4, 'n', 4, '2019-02-12')
,('p003', 3, 2, 'y', 4, '2019-02-12')
,('p004', 4, 2, 'y', 4, '2019-02-12')
,('p005', 5, 2, 'y', 4, '2019-02-12')
,('p001',10, 2, 'n', 4, '2019-02-13')
,('p002', 2, 4, 'n', 4, '2019-02-13')
,('p003', 3, 2, 'y', 4, '2019-02-13')
,('p004', 5, 3, 'n', 4, '2019-02-13')
,('p005', 5, 3, 'y', 8, '2019-02-13')
;

-- This version guesses the min and max dates...
WITH DSpan(minDate, maxDate) AS (
  SELECT MIN(idate), MAX(idate) FROM t GROUP BY idate
), DDays(dayOldDate, dayNewDate) AS (
  SELECT minDate, date(minDate,'+1 day') FROM DSpan
  UNION ALL
  SELECT dayNewDate, date(dayNewDate,'+1 day') FROM DDays, DSpan WHERE DDays.dayNewDate < DSpan.maxDate
), Chg(a, idate, col, oldVal, newVal) AS (
  SELECT DISTINCT tNew.a, tNew.idate, 'b', tOld.b,tNew.b
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.b != tOld.b
UNION ALL
  SELECT DISTINCT tNew.a, tNew.idate, 'c', tOld.c,tNew.c
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.c != tOld.c
UNION ALL
  SELECT DISTINCT tNew.a, tNew.idate, 'd', tOld.d,tNew.d
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.d != tOld.d
UNION ALL
  SELECT DISTINCT tNew.a, tNew.idate, 'e', tOld.e,tNew.e
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.e != tOld.e
)
SELECT Chg.a, Chg.oldVal, Chg.newVal,
       ('Column '||Chg.col||' changed on '||Chg.idate||' from '||Chg.oldVal||' to '||Chg.newVal||'.') AS Change
  FROM Chg
 ORDER BY Chg.a, Chg.idate
;


  -- a    | oldVal | newVal | Change
  -- ---- | ------ | ------ | --------------------------------------------
  -- p001 |    1   |   10   | Column b changed on 2019-02-12 from 1 to 10.
  -- p002 |    2   |    4   | Column c changed on 2019-02-12 from 2 to 4.
  -- p003 |    n   |    y   | Column d changed on 2019-02-12 from n to y.
  -- p004 |    4   |    5   | Column b changed on 2019-02-13 from 4 to 5.
  -- p004 |    2   |    3   | Column c changed on 2019-02-13 from 2 to 3.
  -- p004 |    y   |    n   | Column d changed on 2019-02-13 from y to n.
  -- p005 |    2   |    3   | Column c changed on 2019-02-13 from 2 to 3.
  -- p005 |    4   |    8   | Column e changed on 2019-02-13 from 4 to 8.


-- This version let's you set it, I chose the last two of the days here.
WITH DSpan(minDate, maxDate) AS (
  SELECT '2019-02-12', '2019-02-13'
), DDays(dayOldDate, dayNewDate) AS (
  SELECT minDate, date(minDate,'+1 day') FROM DSpan
  UNION ALL
  SELECT dayNewDate, date(dayNewDate,'+1 day') FROM DDays, DSpan WHERE DDays.dayNewDate < DSpan.maxDate
), Chg(a, idate, col, oldVal, newVal) AS (
  SELECT DISTINCT tNew.a, tNew.idate, 'b', tOld.b,tNew.b
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.b != tOld.b
UNION ALL
  SELECT DISTINCT tNew.a, tNew.idate, 'c', tOld.c,tNew.c
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.c != tOld.c
UNION ALL
  SELECT DISTINCT tNew.a, tNew.idate, 'd', tOld.d,tNew.d
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.d != tOld.d
UNION ALL
  SELECT DISTINCT tNew.a, tNew.idate, 'e', tOld.e,tNew.e
    FROM DDays
    JOIN t AS tOld ON tOld.idate = DDays.dayoldDate
    JOIN t AS tNew ON tNew.idate = DDays.dayNewDate
   WHERE tNew.a = tOld.a AND tNew.e != tOld.e
)
SELECT Chg.a, Chg.oldVal, Chg.newVal,
       ('Column '||Chg.col||' changed on '||Chg.idate||' from '||Chg.oldVal||' to '||Chg.newVal||'.') AS Change
  FROM Chg
 ORDER BY Chg.a, Chg.idate
;


  -- a    | oldVal | newVal | Change
  -- ---- | ------ | ------ | -------------------------------------------
  -- p004 |    4   |    5   | Column b changed on 2019-02-13 from 4 to 5.
  -- p004 |    2   |    3   | Column c changed on 2019-02-13 from 2 to 3.
  -- p004 |    y   |    n   | Column d changed on 2019-02-13 from y to n.
  -- p005 |    2   |    3   | Column c changed on 2019-02-13 from 2 to 3.
  -- p005 |    4   |    8   | Column e changed on 2019-02-13 from 4 to 8.

  --   Script Stats: Total Script Execution Time:     0d 00h 00m and 00.050s   --                 Total Script Query Time:         0d 00h 00m and 00.009s
  --                 Total Database Rows Changed:     15
  --                 Total Virtual-Machine Steps: 6990
  --                 Last executed Item Index:        4
  --                 Last Script Error:
  -- ------------------------------------------------------------------------------------------------

  -- 2020-01-14 00:08:17.900  |  [Success]    Script Success.
  -- 2020-01-14 00:08:17.901  |  [Success]    Transaction Rolled back.
  -- -------  DB-Engine Logs (Contains logged information from all DB connections during run)  ------   -- [2020-01-14 00:08:17.826] APPLICATION : Script E:\Documents\SQLiteAutoScript.sql started at 00:08:17.826 on 14 January.   -- [2020-01-14 00:08:17.890] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.890] ERROR (284) : automatic index on t(a)
  -- [2020-01-14 00:08:17.890] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.890] ERROR (284) : automatic index on t(a)
  -- [2020-01-14 00:08:17.890] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.891] ERROR (284) : automatic index on t(a)
  -- [2020-01-14 00:08:17.891] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.891] ERROR (284) : automatic index on t(a)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on t(a)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on t(a)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on t(a)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on DDays(dayOldDate)
  -- [2020-01-14 00:08:17.896] ERROR (284) : automatic index on t(a)
  -- ================================================================================================



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

Reply via email to