Home > OS >  T-SQL dynamically fill column with calculated data based on differences between row values
T-SQL dynamically fill column with calculated data based on differences between row values

Time:02-04

I am struggling with the following issue (simplified form). I have a table with 53 rows and for column [No of Days] only some of the rows contain a quantity. In the column [Days Calculated] I want to dynamically calculate the Days for the rows that do not contain a quantity, adding the difference between 2 rows with a quantity evenly among the rows without quantity. If there is no difference than use the same quantity.

Rows without a quantity before the first row with a quantity should be filled with quantity of this row. Rows without a quantity after the last row with a quantity should be filled with the quantity of this row.

The source I have are the first 2 columns, I need to add the 3rd column.

Period No No of Days Days Calculated
1 NULL 77
2 NULL 77
3 NULL 77
removed some rows NULL 77
22 77 77
23 NULL 75,83
24 NULL 74,66
25 NULL 73,49
26 NULL 72,32
27 NULL 71,15
28 70 70
29 NULL 70
removed some rows NULL 70
45 70 70
46 NULL 73,50
47 77 77
48 NULL 77
removed some rows NULL 77
53 77 77

I have tried to solve this with making a ranking and a case statement with the possible conditions but have not been able to completely get it right. I have the feeling there are better ways.

Any guidance in the right direction is much appreciated !

CodePudding user response:

CREATE TABLE testTable (PeriodNo INT, NoOfDaysPL MONEY);
INSERT INTO dbo.testTable(PeriodNo)
SELECT TOP(53)ROW_NUMBER() OVER (ORDER BY t1.object_id) AS N
FROM sys.all_columns t1
     CROSS JOIN sys.all_columns AS t2;
UPDATE dbo.testTable SET NoOfDaysPL=77 WHERE PeriodNo=22;
UPDATE dbo.testTable SET NoOfDaysPL=70 WHERE PeriodNo=28;
UPDATE dbo.testTable SET NoOfDaysPL=70 WHERE PeriodNo=45;
UPDATE dbo.testTable SET NoOfDaysPL=77 WHERE PeriodNo=51;

SELECT PeriodNo, NoOfDaysPL, 
    CASE WHEN pv IS NULL THEN COALESCE(NoOfDaysPL, ndv)
         WHEN nv IS NULL THEN COALESCE(NoOfDaysPL, pdv)
         WHEN NoOfDaysPL IS NULL THEN pdv-((pdv-ndv)/(nv-pv)*(PeriodNo-pv))
         ELSE NoOfDaysPL 
    END NoOfDaysCalculated
FROM dbo.testTable AS tt
     CROSS APPLY(SELECT MAX(PeriodNo)
                 FROM dbo.testTable AS tt2
                 WHERE tt2.PeriodNo<tt.PeriodNo AND tt2.NoOfDaysPL IS NOT NULL) p(pv)
     CROSS APPLY(SELECT MIN(PeriodNo)
                 FROM dbo.testTable AS tt2
                 WHERE tt2.PeriodNo>tt.PeriodNo AND tt2.NoOfDaysPL IS NOT NULL) n(nv)
     OUTER APPLY(SELECT NoOfDaysPL FROM dbo.testTable AS tt2 WHERE tt2.PeriodNo=p.pv) pc(pdv)
     OUTER APPLY(SELECT NoOfDaysPL FROM dbo.testTable AS tt2 WHERE tt2.PeriodNo=n.nv) nc(ndv);
PeriodNo NoOfDaysPL NoOfDaysCalculated
1 null 77.0000
2 null 77.0000
3 null 77.0000
4 null 77.0000
5 null 77.0000
6 null 77.0000
7 null 77.0000
8 null 77.0000
9 null 77.0000
10 null 77.0000
11 null 77.0000
12 null 77.0000
13 null 77.0000
14 null 77.0000
15 null 77.0000
16 null 77.0000
17 null 77.0000
18 null 77.0000
19 null 77.0000
20 null 77.0000
21 null 77.0000
22 77.0000 77.0000
23 null 75.8334
24 null 74.6668
25 null 73.5002
26 null 72.3336
27 null 71.1670
28 70.0000 70.0000
29 null 70.0000
30 null 70.0000
31 null 70.0000
32 null 70.0000
33 null 70.0000
34 null 70.0000
35 null 70.0000
36 null 70.0000
37 null 70.0000
38 null 70.0000
39 null 70.0000
40 null 70.0000
41 null 70.0000
42 null 70.0000
43 null 70.0000
44 null 70.0000
45 70.0000 70.0000
46 null 71.1666
47 null 72.3332
48 null 73.4998
49 null 74.6664
50 null 75.8330
51 77.0000 77.0000
52 null 77.0000
53 null 77.0000

fiddle

  • Related