Oracle 19c中基于前一行数据的累计计算/计算
Cumulative calculation/ Calculation based on previous row data in Oracle 19c
如何对一列进行累加计算,根据同一列但前一行的数据计算出一个值?
例如:考虑下面table和记录
数据-
CREATE TABLE TEST ( DT DATE, NAME VARCHAR2(10), AMOUNT NUMBER(10,3));
insert into TEST values ( to_date( '01-jan-2021'), 'apple', 198.95 );
insert into TEST values ( to_date( '02-jan-2021'), 'apple', 6.15 );
insert into TEST values ( to_date( '03-jan-2021'), 'apple', 4.65 );
insert into TEST values ( to_date( '04-jan-2021'), 'apple', 20.85 );
insert into TEST values ( to_date( '01-jan-2021'), 'banana', 80.5 );
insert into TEST values ( to_date( '02-jan-2021'), 'banana', 9.5 );
insert into TEST values ( to_date( '03-jan-2021'), 'banana', 31.65 );
期望输出:
DT NAME AMOUNT CALC
---------------------------------
1-Jan-21 apple 198.95 39.79
2-Jan-21 apple 6.15 33.062
3-Jan-21 apple 4.65 27.380
4-Jan-21 apple 20.85 26.074
.
.
.
1-Jan-21 banana 80.5 16.1
2-Jan-21 banana 9.5 14.78
3-Jan-21 banana 31.65 18.14
.
.
.
我需要根据以下公式编写查询以获取每条记录(按名称分组)的 CALC:
((CALC of prev day record * 4)+ AMOUNT of current record )/ 5
i.e for APPLE
for 1-jan-21, CALC = ((0*4)+198.95)/5 = 39.79 -------> since it is 1st record, have taken 0 as CALC of prev day record
for 2-jan-21, CALC = ((39.79*4)+6.15)/5= 33.062 -----> prev CALC is considered from 1-jan-21 - 39.79 and 6.15 from current row
for 3-jan-21, CALC = ((33.062*4)+4.65)/5= 27.380 and so on
For BANANA
1-jan-21, CALC = ((0*4)+80.5)/5=16.1
1-jan-21, CALC = ((16.1*4)+9.5)/5=14.78
etc
我尝试过使用 lag、with、join 等,也查看了互联网但无法找到解决方案。
提前致谢!
如果连续行的金额为:a1、a2、a3, ...
那么连续行的 calc
值为:
- a1 × (40 ÷ 51)
- a1 × (41 ÷ 52) + a2 × (40 ÷ 51)
- a1 × (42 ÷ 53) + a2×(41÷52)+a3× (40 ÷ 51)
- ...
您可以使用它(以及您的数据连续几天的事实)来计算查询的进展:
SELECT t2.dt,
t2.name,
t2.amount,
SUM(POWER(4/5, t2.dt - t1.dt) * t1.amount / 5) AS calc
FROM test t1
INNER JOIN test t2
ON (t1.name = t2.name AND t1.dt <= t2.dt)
GROUP BY
t2.dt,
t2.name,
t2.amount
ORDER BY
t2.name,
t2.dt;
您还可以使用 MODEL
子句:
SELECT dt,
name,
amount,
calc
FROM (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY dt) AS rn
FROM test t
)
MODEL
PARTITION BY (name)
DIMENSION BY (rn)
MEASURES ( dt, amount, 0 AS calc)
RULES (
calc[1] = amount[1]/5,
calc[rn>1] = (amount[cv(rn)] + 4*calc[cv(rn)-1])/5
)
其中,对于您的示例数据,两者都输出:
DT
NAME
AMOUNT
CALC
01-JAN-21
apple
198.95
39.79
02-JAN-21
apple
6.15
33.062
03-JAN-21
apple
4.65
27.3796
04-JAN-21
apple
20.85
26.07368
01-JAN-21
banana
80.5
16.1
02-JAN-21
banana
9.5
14.78
03-JAN-21
banana
31.65
18.154
db<>fiddle here
如何对一列进行累加计算,根据同一列但前一行的数据计算出一个值?
例如:考虑下面table和记录
数据-
CREATE TABLE TEST ( DT DATE, NAME VARCHAR2(10), AMOUNT NUMBER(10,3));
insert into TEST values ( to_date( '01-jan-2021'), 'apple', 198.95 );
insert into TEST values ( to_date( '02-jan-2021'), 'apple', 6.15 );
insert into TEST values ( to_date( '03-jan-2021'), 'apple', 4.65 );
insert into TEST values ( to_date( '04-jan-2021'), 'apple', 20.85 );
insert into TEST values ( to_date( '01-jan-2021'), 'banana', 80.5 );
insert into TEST values ( to_date( '02-jan-2021'), 'banana', 9.5 );
insert into TEST values ( to_date( '03-jan-2021'), 'banana', 31.65 );
期望输出:
DT NAME AMOUNT CALC
---------------------------------
1-Jan-21 apple 198.95 39.79
2-Jan-21 apple 6.15 33.062
3-Jan-21 apple 4.65 27.380
4-Jan-21 apple 20.85 26.074
.
.
.
1-Jan-21 banana 80.5 16.1
2-Jan-21 banana 9.5 14.78
3-Jan-21 banana 31.65 18.14
.
.
.
我需要根据以下公式编写查询以获取每条记录(按名称分组)的 CALC:
((CALC of prev day record * 4)+ AMOUNT of current record )/ 5
i.e for APPLE
for 1-jan-21, CALC = ((0*4)+198.95)/5 = 39.79 -------> since it is 1st record, have taken 0 as CALC of prev day record
for 2-jan-21, CALC = ((39.79*4)+6.15)/5= 33.062 -----> prev CALC is considered from 1-jan-21 - 39.79 and 6.15 from current row
for 3-jan-21, CALC = ((33.062*4)+4.65)/5= 27.380 and so on
For BANANA
1-jan-21, CALC = ((0*4)+80.5)/5=16.1
1-jan-21, CALC = ((16.1*4)+9.5)/5=14.78
etc
我尝试过使用 lag、with、join 等,也查看了互联网但无法找到解决方案。
提前致谢!
如果连续行的金额为:a1、a2、a3, ...
那么连续行的 calc
值为:
- a1 × (40 ÷ 51)
- a1 × (41 ÷ 52) + a2 × (40 ÷ 51)
- a1 × (42 ÷ 53) + a2×(41÷52)+a3× (40 ÷ 51)
- ...
您可以使用它(以及您的数据连续几天的事实)来计算查询的进展:
SELECT t2.dt,
t2.name,
t2.amount,
SUM(POWER(4/5, t2.dt - t1.dt) * t1.amount / 5) AS calc
FROM test t1
INNER JOIN test t2
ON (t1.name = t2.name AND t1.dt <= t2.dt)
GROUP BY
t2.dt,
t2.name,
t2.amount
ORDER BY
t2.name,
t2.dt;
您还可以使用 MODEL
子句:
SELECT dt,
name,
amount,
calc
FROM (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY dt) AS rn
FROM test t
)
MODEL
PARTITION BY (name)
DIMENSION BY (rn)
MEASURES ( dt, amount, 0 AS calc)
RULES (
calc[1] = amount[1]/5,
calc[rn>1] = (amount[cv(rn)] + 4*calc[cv(rn)-1])/5
)
其中,对于您的示例数据,两者都输出:
DT NAME AMOUNT CALC 01-JAN-21 apple 198.95 39.79 02-JAN-21 apple 6.15 33.062 03-JAN-21 apple 4.65 27.3796 04-JAN-21 apple 20.85 26.07368 01-JAN-21 banana 80.5 16.1 02-JAN-21 banana 9.5 14.78 03-JAN-21 banana 31.65 18.154
db<>fiddle here