Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
167 views
in Technique[技术] by (71.8m points)

postgresql - I need to multiply two column (A1 * B1) and the answer present at B2 then multiply the A2 value * B2 value

I have paste the details as below,

The detailed requirements are here:

The detailed sheet attached please click here

Sno     Column A        Column B        Column C        Formula
1       0 -1 Yrs        0.963190184     100000      
2       1-4 Yrs         0.992394232     96319       (B1 * C1 (default value 100000)) =C2
3       5 - 9 Yrs       0.994964922     95586       (B2 * C2 ) =C3
4       10 - 14 Yrs     0.998372661     95105       (B3 * C3 ) =C4
5       15 - 19 Yrs     0.994485603     94950       
6       20- 24 Yrs      0.992903887     94427       
7       25 - 29 Yrs     0.994008987     93757       
8       30 - 34 Yrs     0.994041445     93195       
9       35 - 39 Yrs     0.991283828     92640       
10      40 - 44 Yrs     0.987141228     91832       

The above same formula needs to be apply for the remaining columns through a PostgreSQL query.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Since your basic requirement is looking back to the prior row the lag function first comes to mind. However this dos not work as the necessary value is being calculated of the fly and lag operates on the result set (prior to lag operation). So we turn to a recursive query where at each recursion we have available the just calculated on the prior recursion. This of course assumes the other columns are already loaded. We get the desired values with:

with recursive demo( rno, r_colb, r_colc) as 
     ( select 0, 1::numeric,  100000::numeric    -- prime the recursion 
       union all 
       select sno, column_b,  r_colb*r_colc
        from test 
        join demo  
          on (sno = rno+1)                       -- next sno  
     )
select rno, r_colb, round(r_colc) r_colc
  from demo ;

That does not get to the final need - updating the table. Fortunately, Postgres supports "update ... from (subquery) where ..." structure and the subquery just basically needs to be a valid query; including the above. So we arrive at:

update test 
   set column_c = r_colc
  from (
        with recursive demo( rno, r_colb, r_colc) as 
             ( select 0, 1::numeric,  100000::numeric    -- prime the recursion 
               union all 
               select sno, column_b,  r_colb*r_colc
                from test 
                join demo  
                  on (sno = (select min(sno)             -- since I do trust autogenerated ids 
                               from test                 -- to actually be in perfect sequence
                              where sno > rno))    
             )
        select rno, r_colb, round(r_colc) r_colc
          from demo 
        ) s
  where sno = rno;  

See demo run in v9.6.


In response to "applied for continuous calculation", yes that is possible and actually only changing the WITH clause to prime the recursion. But first, when speaking on SQL remove IF from your vocabulary - there is no such thing. There are conditionals (where, case, when...) but no IF.
The non-recursive query just gets the last known value then the recursive part looks at each subsequent and calculates column_c from it. To restart the calculation, just do the same. I modified the update query to do just that. See revised demo. It would have been possible to just modify the non-recursive query to select sno 10 (the last known value for column_c). But doing so would require updating the query for subsequent execution. Instead it looks for the last know (not null column_c) selecting that as the primer. This does require all new rows leave column_c null. But it should be good for any number of additional rows.
Note: The term "prime/primer" is my terminology for this query. It is not a general technical term used with a recursive CTE.

update test     
   set column_c = r_colc   
  from (
        with recursive demo( rno, r_colb, r_colc) as 
             ( select sno, column_b, column_c    -- prime the recursion 
                 from test 
                where sno = (select max(sno)
                               from test 
                              where column_c is not null 
                            ) 
               union all 
               select sno, column_b,  r_colb*r_colc
                from test 
                join demo  
                  on (sno = (select min(sno)             -- since I do trust autogenerated ids 
                               from test                 -- to actually be in perfect sequence
                              where sno > rno))    
             )
        select rno, r_colb, round(r_colc) r_colc
          from demo 
        ) s

where sno = rno;


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...