1

Hello everyone I was trying to create running pending value like running total as I am so close but I was not able to do it. It produces some wrong output

Here is the sqlite export code to create tables and data.

BEGIN TRANSACTION;
CREATE TABLE "tab_in" (
   id INTEGER PRIMARY KEY ASC AUTOINCREMENT, 
   "type" TEXT NOT NULL, "grams" INTEGER NOT NULL
);
INSERT INTO `tab_in` VALUES (1,'type1',1000);
INSERT INTO `tab_in` VALUES (2,'type2',2000);
CREATE TABLE "sub_" (
   id INTEGER PRIMARY KEY ASC AUTOINCREMENT, 
   "gram1" REAL, "gram2" REAL, 
   "gram3" REAL, 
   "_date" TEXT, 
   "id_sub" INTEGER, 
   "record_count" INTEGER, 
   FOREIGN KEY(id_sub) REFERENCES sub(id)
);
INSERT INTO `sub_` VALUES (5,10.0,NULL,NULL,'2017-06-01 00:00:00.000',2,2);
INSERT INTO `sub_` VALUES (7,1.45,NULL,NULL,'2017-06-01 00:00:00.000',1,3);
INSERT INTO `sub_` VALUES (8,12.6,NULL,NULL,'2017-06-01 00:00:00.000',1,4);
INSERT INTO `sub_` VALUES (9,NULL,13.3,NULL,'2017-06-02 00:00:00.000',2,5);
INSERT INTO `sub_` VALUES (10,NULL,NULL,20.46,'2017-06-02 00:00:00.000',2,6);
INSERT INTO `sub_` VALUES (11,6.23,NULL,NULL,'2017-06-02 00:00:00.000',2,7);
CREATE TABLE "sub" (
   id INTEGER PRIMARY KEY ASC AUTOINCREMENT, 
   "_date" TEXT NOT NULL, 
   "gram" REAL NOT NULL, 
   "id_tab_in" INTEGER NOT NULL, 
   "record_count" INTEGER, 
   FOREIGN KEY(id_tab_in) REFERENCES tab_in(id)
);
INSERT INTO `sub` VALUES (1,'2017-05-30 00:00:00.000',14.05,1,1);
INSERT INTO `sub` VALUES (2,'2017-05-30 00:00:00.000',50.0,2,2);
COMMIT;

Here is the query that I have been working on but couldn't make it work.

SELECT DISTINCT 
   "sub_"."_date" as "sub_._date",
   "sub_"."gram1" as "sub_.gram1",
   "sub_"."gram2" as "sub_.gram2",
   "sub_"."gram3" as "sub_.gram3",
   ( 
     (SELECT sub.gram FROM sub WHERE sub.id=sub_.id_sub) -  
     (
        SELECT ifnull(TOTAL(s.gram1), 0) +
               ifnull(TOTAL(s.gram2), 0) +
               ifnull(TOTAL(s.gram3), 0) 
        FROM sub_ s 
        WHERE (s.id_sub=sub_.id_sub) 
          AND (s.record_count <= sub_.record_count )
      )
    )    AS 'sub_.pending',
   "sub_".id,
   "sub_"."id_sub" as "sub_.id_sub" 
 FROM "sub_" 
 LEFT OUTER JOIN "sub" ON "sub_"."id_sub"="sub".id 
 WHERE "sub_"."id_sub"=1;

Output of this query is (For sub.id = 1 value of sub.gram is 14.05) basically what I'm doing here, To calculate pending value I am subtracting from sub.gram using total of sub_.gram1, sub_.gram2, sub_.gram3.

sub_._date                 sub_.gram1   sub_.gram2  sub_.gram3  sub_.pending            id  sub_.id_sub
2017-06-01 00:00:00.000     1.45         (null)     (null)     12.600000000000001       7   1
2017-06-01 00:00:00.000     12.6         (null)     (null)     1.7763568394002505e-15   8   1

Desired output for sub_.pending is

sub_.pending
12.6
0

Please help me to make it work.

  • 1
    The term "running pending" is unknown to me. Can you explain in prose what you want to achieve? Can you give expected output? Can you explain how the output of your query fails to satisfy you? Otherwise nice mcve for a first question, my compliments. – Yunnosch Jun 03 '17 at 05:22
  • For ID 1 I get sub.gram = 14.05, sub_.gram1+2+3 = 14.05. Diff = 0. For ID 2 I get sub.gram = 50, sub_.gram1+2+3 = 49.99. Diff = 0.01. This doesn't match your expected results. So what is *your* formula to add up the sub_ grams? – Thorsten Kettner Jun 03 '17 at 05:34
  • What are the `record_count` columns for? They don't seem to make much sense on first glance. – Thorsten Kettner Jun 03 '17 at 05:40
  • Still not sure what you mean, can you explain using English sentences (i.e. prose) instead of giving a value? – Yunnosch Jun 03 '17 at 05:48
  • @Yunnosch running total example https://stackoverflow.com/questions/860966/calculate-a-running-total-in-sql-server i am using same fundamental but instead of it showing cumulative total I want to show cumulative pending or running pending so I am subtracting it from parent value in my case for id=1 sub.gram 14.05 – user8104189 Jun 03 '17 at 06:08
  • So "running pending" would mean the difference between the current sum of "gram"s (those not NULL) and the previous sum of "gram"s? – Yunnosch Jun 03 '17 at 06:13
  • @ThorstenKettner for For Sub.ID = 1 I get sub.gram = 14.05, sub_.gram1+2+3 = 14.05.than Diff = 0 but I am not getting that as answer instead of it I am getting Pending value like 1.7763568394002505e-15 not 0 – user8104189 Jun 03 '17 at 06:13
  • Can you focus your question on the caluclation of running pending? E.g. by working on a simpler toy database, which does not require the calculation of gram1+gram2+gram3 and does not contain unused information (e.g. dates). – Yunnosch Jun 03 '17 at 06:20
  • @Yunnosch ok I will Make it more simple and will also add fiddle for it give me some time thanks for help me out – user8104189 Jun 03 '17 at 06:24
  • That's the spirit (no sarcasm). By the way (should have mentioned earlier), you might find useful ideas by taking the [tour]. – Yunnosch Jun 03 '17 at 06:27
  • Your problems stem from the data type `REAL`. I've updated my answer (which originally only showed about the same query as your own, as I had finally understood the task, not noticing yet, that your only issue was decimals). – Thorsten Kettner Jun 03 '17 at 06:29

1 Answers1

0

Okay, I got it now. You query is correct, though you unnecessarily query sub twice.

Your problem is with your data type. You are storing values as REAL. This is an approximate data type. So you think you are storing 12.6, but it gets stored as 12.600000000000001 for instance. This is something we would normally never do in a database. We would always store exact values. SQLite, however, is very poor considering this, as it doesn't even provide an exact type for decimal numbers.

So in SQLite your best bet seems to be to round. Say you know that your values are only valid up to two decimal places you'd ROUND(value,2):

UPDATE: The rounded values would probably be REALs again :-( Finally your results are correct, only imprecise. So format your output with two decimal places using printf:

select 
  sub_.*,
  printf('%.2f',
    sub.gram -
    (
      select 
        coalesce(sum(s.gram1), 0) +
        coalesce(sum(s.gram2), 0) +
        coalesce(sum(s.gram3), 0)
      from sub_ s
      where s.id_sub = sub_.id_sub
        and s.record_count <= sub_.record_count
    )
  ) as pending
from sub_
join sub on sub.id = sub_.id_sub
order by sub_.id_sub, sub_.record_count;
Thorsten Kettner
  • 89,309
  • 7
  • 49
  • 73
  • thank you so much for help can you please change line "where s.id_sub = sub_id_sub" to "where s.id_sub = sub_.id_sub" so people who might find this useful can have correct answer also why coalesce instead of ifnull will it make any difference ?? – user8104189 Jun 03 '17 at 07:16
  • Ah, a missing dot. Thanks. No, `COALESCE` makes no difference. It's just the standard SQL function, whereas `IFNULL` is propriatary. I prefer the standard functions when available. – Thorsten Kettner Jun 03 '17 at 07:22