with t as( select 1 val from dual union all select 3 from dual union all select 5 from dual union all select 7 from dual union all select 9 from dual) select rownum, sum(sum(val)) over (order by rownum rows between unbounded preceding and current row) sum_val from t group by rownum order by rownum; ROWNUM SUM_VAL ---------- ---------- 1 1 2 4 3 9 4 16 5 25
SQL> with t as( 2 select 1 val from dual union all 3 select 3 from dual union all 4 select 5 from dual union all 5 select 7 from dual union all 6 select 9 from dual) 7 select val, 8 sum(sum(val)) 9 over (order by rownum rows between unbounded preceding and current row) 10 sum_val 11 from t 12 group by rownum,val 13 order by rownum; VAL SUM_VAL ---------- ---------- 1 1 3 4 5 9 7 16 9 25
sum(sum(val)) over (order by rownum rows between unbounded preceding and current row)是连在一起的吗?
WITH cte AS ( SELECT c1,ROWNUM AS Row_num FROM t1 ) SELECT m.c1,sum(n.c1) FROM cte m,cte n WHERE n.row_num < =m.row_num GROUP BY m.c1 ORDER BY m.c1;------res 1 1 1 2 3 4 3 5 9 4 7 16 5 9 25
with t as( select 1 val from dual union all select 3 from dual union all select 5 from dual union all select 7 from dual union all select 9 from dual) select val, decode(mod(rownum, 2), 1, 1, -1) * sum(val * decode(mod(rownum, 2), 1, 1, -1)) over(order by val) from t 1 1 3 2 5 3 7 4 9 5
select val, decode(mod(rownum, 2), 1, 1, -1) * sum(val * decode(mod(rownum, 2), 1, 1, -1)) over(order by val) from t
我再补充说明一下,这个问题的关键点在于构造一个函数,这个函数对,1.每一行输入的数据,2.它自身在前1行计算得到函数值,这样两个部分进行混合的逻辑运算,然后返回一个函数值.其最简单的特例是f(t)=x+f(t-1),其一般化的表达式是f(t)=f(x,f(t-1).问题的难点在于,如何在这个function内部,获得上一行计算得出的函数值. 我目前在试图使用oracle data cartridges中的pipeline table function做. 似乎是有个希望的方向.
网上查了一下,oracle还是支持递归函数的调用的 如果能增加一个id列的话create or replace function 递归(x in int) return integer is n INTEGER; begin SELECT num_col INTO n FROM t1 WHERE id=x; IF x=1 THEN RETURN n; ELSE RETURN n+递归(x-1); END IF; end 递归; SQL> SELECT id,num_col from t1;
不想增加字段的话应该可以create or replace function 递归(x in int) return integer is n INTEGER; begin SELECT num_col INTO n FROM (SELECT num_col,rownum rn from t1) WHERE rn=x; IF x=1 THEN RETURN n; ELSE RETURN n+递归(x-1); END IF; end 递归;
把你的代码贴出来,咋也学习学习! create function gen_numbers(n in number default null) return array PIPELINED as begin for i in 1 .. nvl(n,999999999) loop pipe row(i); end loop; return; end; /Function created.select * from TABLE(gen_numbers(3)); COLUMN_VALUE ------------ 1 2 3 select * from ( select * from (select * from table(gen_numbers(49))) order by dbms_random.random ) where rownum <= 6 / COLUMN_VALUE ------------ 47 42 40 15 48 23
代码因为是在一个大系统里的,较为冗长,贴出来看起来可能会很麻烦,我只讲一下简单原理吧.pipeline函数,它的作用是产生一个嵌套表,这个嵌套表可以象一个普通表一样被sql语句使用. 那么piepline函数如何产生嵌套表的数据呢,2种方法,1是根据某种逻辑直接产生(如你上面的例子),2是调用者传一个ref cursor给它,它对这个ref cursor里的数据做出某种加工,在放到嵌套表里.我做的工作,就是创建一个object,在object的成员函数中把f(t)的逻辑封装进去.同时,通过这个object的attribute来记录下我需要的f(t-1),f(t-2)...值最后就是调用工作,通过cursor语句打开一个ref cursor,把数据传给pipeline函数,pipeline函数调用我的定义object的成员函数,计算出结果,返回给pipeline函数,pipeline函数再把结果返回给调用它的sql语句.sql语句拿到的数据,就跟普通表一样,没啥区别.假设pipeline函数名为pf,那么最终的调用形式就是这样的 SELECT * FROM TABLE(pf(CURSOR(SELECT * FROM T1))); 这里,CURSOR子句是oracle自带的,它的作用是返回SELECT * FROM T1的ref cursor. pf返回一个嵌套表,但无法直接被sql语句使用,需要外面再加一个TABLE(),这也是oracle自带的.先说这么多,关于pipeline函数的详细内容,大家可参考Oracle® Database Data Cartridge Developer's Guide第13章. 在oracle网站上有.
with t as(
select 1 val from dual union all
select 3 from dual union all
select 5 from dual union all
select 7 from dual union all
select 9 from dual)
select rownum,
sum(sum(val))
over (order by rownum rows between unbounded preceding and current row)
sum_val
from t
group by rownum
order by rownum;
ROWNUM SUM_VAL
---------- ----------
1 1
2 4
3 9
4 16
5 25
SQL> with t as(
2 select 1 val from dual union all
3 select 3 from dual union all
4 select 5 from dual union all
5 select 7 from dual union all
6 select 9 from dual)
7 select val,
8 sum(sum(val))
9 over (order by rownum rows between unbounded preceding and current row)
10 sum_val
11 from t
12 group by rownum,val
13 order by rownum; VAL SUM_VAL
---------- ----------
1 1
3 4
5 9
7 16
9 25
over (order by rownum rows between unbounded preceding and current row)是连在一起的吗?
实际这个f(t)可能会包含非常复杂的逻辑,这里我只是给出了一个最简单的形式.
仅用分析函数怕是搞不定的.
逻辑复杂,if-then-elsif , case when , for loop...
这些不是可以处理吗?
关于oracle中的递归,还真的不懂......
SELECT c1,ROWNUM AS Row_num FROM t1
)
SELECT m.c1,sum(n.c1) FROM cte m,cte n
WHERE n.row_num < =m.row_num
GROUP BY m.c1
ORDER BY m.c1;------res
1 1 1
2 3 4
3 5 9
4 7 16
5 9 25
with t as(
select 1 val
from dual
union all
select 3
from dual
union all
select 5
from dual
union all
select 7
from dual
union all
select 9 from dual)
select val,
decode(mod(rownum, 2), 1, 1, -1) * sum(val * decode(mod(rownum, 2), 1, 1, -1)) over(order by val)
from t
1 1
3 2
5 3
7 4
9 5
decode(mod(rownum, 2), 1, 1, -1) *
sum(val * decode(mod(rownum, 2), 1, 1, -1)) over(order by val)
from t
我目前在试图使用oracle data cartridges中的pipeline table function做.
似乎是有个希望的方向.
如果能增加一个id列的话create or replace function 递归(x in int) return integer is
n INTEGER;
begin
SELECT num_col INTO n FROM t1 WHERE id=x;
IF x=1 THEN
RETURN n;
ELSE
RETURN n+递归(x-1);
END IF;
end 递归;
SQL> SELECT id,num_col from t1;
ID NUM_COL
--- ---------------------------------------
1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
10 9
11 10
11 rows selected
SQL> SELECT id,num_col,递归(id) from t1;
ID NUM_COL 递归(ID)
--- --------------------------------------- ----------
1 0 0
2 1 1
3 2 3
4 3 6
5 4 10
6 5 15
7 6 21
8 7 28
9 8 36
10 9 45
11 10 55
11 rows selected
n INTEGER;
begin
SELECT num_col INTO n FROM
(SELECT num_col,rownum rn from t1) WHERE rn=x;
IF x=1 THEN
RETURN n;
ELSE
RETURN n+递归(x-1);
END IF;
end 递归;
因为,需要在sql语句中调用这种类型的函数,例如select f(c1) from t1
当然,这种函数可以算是一种递归函数,但递归这种处理方式却不适合这种函数.
因为递归是嵌套调用的,假设这个表中有100万行记录,那就要嵌套调用100万次.
pl/sql的堆栈能支持100万次嵌套吗?如果是1000万记录呢,1亿记录呢.....终归不是个办法.
create function
gen_numbers(n in number default null)
return array
PIPELINED
as
begin
for i in 1 .. nvl(n,999999999)
loop
pipe row(i);
end loop;
return;
end;
/Function created.select * from TABLE(gen_numbers(3)); COLUMN_VALUE
------------
1
2
3
select *
from (
select *
from (select * from table(gen_numbers(49)))
order by dbms_random.random
)
where rownum <= 6
/ COLUMN_VALUE
------------
47
42
40
15
48
23
代码因为是在一个大系统里的,较为冗长,贴出来看起来可能会很麻烦,我只讲一下简单原理吧.pipeline函数,它的作用是产生一个嵌套表,这个嵌套表可以象一个普通表一样被sql语句使用.
那么piepline函数如何产生嵌套表的数据呢,2种方法,1是根据某种逻辑直接产生(如你上面的例子),2是调用者传一个ref cursor给它,它对这个ref cursor里的数据做出某种加工,在放到嵌套表里.我做的工作,就是创建一个object,在object的成员函数中把f(t)的逻辑封装进去.同时,通过这个object的attribute来记录下我需要的f(t-1),f(t-2)...值最后就是调用工作,通过cursor语句打开一个ref cursor,把数据传给pipeline函数,pipeline函数调用我的定义object的成员函数,计算出结果,返回给pipeline函数,pipeline函数再把结果返回给调用它的sql语句.sql语句拿到的数据,就跟普通表一样,没啥区别.假设pipeline函数名为pf,那么最终的调用形式就是这样的
SELECT * FROM TABLE(pf(CURSOR(SELECT * FROM T1)));
这里,CURSOR子句是oracle自带的,它的作用是返回SELECT * FROM T1的ref cursor.
pf返回一个嵌套表,但无法直接被sql语句使用,需要外面再加一个TABLE(),这也是oracle自带的.先说这么多,关于pipeline函数的详细内容,大家可参考Oracle® Database Data Cartridge Developer's Guide第13章. 在oracle网站上有.
Oracle Pipelined Table Functions简介
[个人能力有限]