简体   繁体   English

Oracle PL / SQL:访问当前行中的上一行计算值

[英]Oracle PL/SQL : Accessing previous row calculated value in current row

Trying to calculate the column's value wherein the value is getting calculated based on previous row's calculated value. 尝试计算列的值,其中将根据上一行的计算值来计算该值。 (As in the image below ) (如下图所示)

图片

which has column Z which is a calculated column as a product of X*Y, case when there is no previous row the value of Y column should be 1 else the value should be previous Z column value. 其中的Z列是X * Y的乘积,是计算所得的列,如果没有前一行,则Y列的值应为1,否则该值应为Z列的前值。

This can be achieved using Cursor's but trying to find it using SQL Query. 可以使用Cursor来实现,但是尝试使用SQL Query来找到它。

It looks like what you're trying to do is do a cumulative multiplication across all the rows. 看来您要执行的操作是对所有行进行累加运算。

You can do this by using a mathematical trick (aka natural logs and exponentials), where you do a cumulative sum of the natural logs of the x values, and then convert the results back to integers using the exponential function: 您可以通过使用数学技巧(也称为自然对数和指数)来做到这一点,在此您可以对x值的自然对数进行累加和,然后使用指数函数将结果转换回整数:

WITH your_table AS (SELECT 'ABC' a, 12 x FROM dual UNION ALL
                    SELECT 'BBC' a, 20 x FROM dual UNION ALL
                    SELECT 'CBC' a, 10 x FROM dual UNION ALL
                    SELECT 'XYZ' a, 5 x FROM dual)
 SELECT a,
       x,
       LAG(z, 1, 1) OVER (ORDER BY a) y,
       z
FROM   (SELECT a,
               x,
               EXP(SUM(LN(x)) OVER (ORDER BY a)) z
        FROM   your_table);

A            X          Y          Z
--- ---------- ---------- ----------
ABC         12          1         12
BBC         20         12        240
CBC         10        240       2400
XYZ          5       2400      12000

Then, if you need to see the previous value (aka your y column), you can throw a lag() around the calculated column to find the previous row's value (and if there is no previous row, assign a 1 to it). 然后,如果需要查看前一个值(又名y列),则可以在计算出的列周围抛出lag()来查找前一行的值(如果没有前一行,则为其分配1)。


ETA: If you already have a table with the information in it, adding a new row becomes a matter of finding the last row and using that to multiply with the new x value. 预计到达时间:如果您已经有了一个包含信息的表,那么添加新行就成为查找最后一行并将其与新x值相乘的问题。 Eg: 例如:

insert into your_table (a, x, y, z)
select 'YMX' a, 2 x, z as new_y, 2*z as new_z
from   (select z,
               row_number() over (order by a desc) rn
        from   your_table)
where  rn = 1;

This finds the latest row (we use the row_number() analytic function to label the rows, starting with the latest a value (which belongs to the last row)), and we can then use the z value from that row to find the new y value, and multiply it by the new x value to find the new z value. 这会找到最新的行(我们使用row_number()分析函数来标记行,从最新的值开始(属于最后一行)),然后可以使用该行的z值来查找新行y值,然后乘以新的x值以找到新的z值。

Then you just need to insert this row. 然后,您只需要插入此行。

I think the simplest method doesn't use lag() or a subquery at all. 我认为最简单的方法根本不使用lag()或子查询。 One method is simple division: 一种方法是简单划分:

SELECT a, x, y
       ( EXP(SUM(LN(x * y)) OVER (ORDER BY a)) ) / (x * y) as z
FROM t;

Or use a window clause with coalesce() : 或者将window子句与coalesce()

SELECT a, x, y
       COALESCE( EXP(SUM(LN(x * y)) OVER (ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)), 1 ) as z
FROM t;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM