这是非常简单相乘作为窗口函数的集合。
您没有指定您的DBMS,因此以下是针对PostgreSQL的。
创建测试表:
create table adi (id integer, postdate date, return integer);
insert into adi (id, postdate, return)
values
(1001, date '2013-07-01', 100),
(1001, date '2013-07-02', 101),
(1001, date '2013-07-03', 102),
(1001, date '2013-07-04', 103);
创建乘以所有值的集合:
create aggregate mult(bigint)
(
sfunc = int8mul,
stype=bigint
);
我们需要一个结果数行,并保留第一行的return
值。
select id,
postdate,
return,
row_number() over (order by postdate) as rn,
first_value(return) over (order by postdate) as base_value
from adi
有了这个结果,我们可以创建最终的查询:
with numbered as (
select id,
postdate,
return,
row_number() over (order by postdate) as rn,
first_value(return) over (order by postdate) as base_value
from adi
)
-- only get the first row, so that the return value of that
-- is not included in the running aggregate
select id,
postdate,
return,
return as linkedvalue
from numbered
where rn = 1
union all
select id,
postdate,
return,
(mult(return) over (order by postdate))::numeric/(case when rn > 2 then base_value else 1 end)
from numbered
where rn > 1;
这将返回以下结果:
id | postdate | return | linkedvalue
-----+------------+--------+------------
1001 | 2013-07-01 | 100 | 100
1001 | 2013-07-02 | 101 | 101.00
1001 | 2013-07-03 | 102 | 103.02
1001 | 2013-07-04 | 103 | 10611.06
查询这可以使用窗口函数来完成除了自定义聚合函数之外,它几乎是标准的ANSI SQL。如何为您正在使用的DBMS定义一个取决于该DBMS。
没有能力创建自定义聚合,这可以使用递归CTE来完成。以下是没有任何产品特定语法的标准ANSI SQL:
with recursive numbered as (
select id,
postdate,
return,
row_number() over (order by postdate) as rn,
first_value(return) over (order by postdate) as base_value
from adi
), calc as (
select id, postdate, return, return as linkedvalue, base_value, rn
from numbered
where rn = 1
union all
select c.id, c.postdate, c.return,
case when c.rn > 2 then (c.return * p.linkedvalue) else c.return end,
p.base_value,
c.rn
from numbered c
join calc p on c.rn - 1 = p.rn
where c.rn > 1
)
select id, postdate, return,
case when
rn > 2 then cast(linkedvalue as numeric)/100
else linkedvalue
end as linkedvalue
from calc
order by postdate;
您使用的是什么rdbms? –
将自定义聚合作为窗口函数应该很容易。你如何定义行的顺序?在一个关系数据库中,除非你有'按顺序'的东西,否则不存在“第一行”。您的示例中行的顺序是由“postdate”列定义的吗?或不同的列? –
这个例子不清楚。可能是LinkedValues是100,10100,1030200,106110600? – knagaev