在Oracle 10中进行嵌套cos()计算

6

我有一个包含一些正整数的表格

n
----
1
2
5
10

对于这个表的每一行,我想要通过SQL语句计算值为cos(cos(...cos(0)..))cos被应用n次)(不允许使用PL/SQL存储过程和函数):
n   coscos
--- --------
1   1
2   0.540302305868
5   0.793480358743
10  0.731404042423

我可以使用递归查询在Oracle 11g中实现这一点。
在Oracle 10g中是否也可能实现相同的功能?


你为什么要这样做呢?让Oracle发挥其所擅长的数据库功能,不要让它进行额外的计算。这些计算可以很容易地转移到任何你喜欢的编程语言中。此外,考虑将该值存储在数据库中的单独列中。 - Woot4Moo
@Woot4Moo - 请不要在我的帖子中传播你的信仰“只使用 Oracle 存储数据而没有任何计算”。;-) - Egor Skriptunoff
我几乎不会称之为宗教。问题在于你手里有一把锤子(Oracle),而所有的东西都是钉子(解决数学问题)。这与人们使用正则表达式来解析HTML的做法是一样的。更好的问题是,为什么你想在Oracle中这样做,你得到了什么性能上的好处?如果你能解释清楚,我很乐意帮你找到一个解决方案。 - Woot4Moo
@Woot4Moo - 看起来你害怕使用Oracle的全部功能,所以我认为这是你的信仰(在我看来,任何宗教都是一组奇怪的限制)。请在本帖之外讨论诸如“在Oracle中进行数学计算是好还是坏”的问题。 - Egor Skriptunoff
伟大的问题Egor!我知道你不只是在计算COS,而是在问一些更深的东西。我看过你的帖子,所以我可以假设你已经尝试过使用CONNECT BY LEVEL做了一些事情,但并没有起作用。我这里没有什么可行的方法。我建议你向更高的权威——即Ask Tom寻求帮助。 - Ed Gibbs
2个回答

4
MODEL子句可以解决此问题:
测试数据:
create table test1(n number unique);
insert into test1 select * from table(sys.odcinumberlist(1,2,5,10));
commit;

查询:

--The last row for each N has the final coscos value.
select n, coscos
from
(
    --Set each value to the cos() of the previous value.
    select * from
    (
        --Each value of N has N rows, with value rownumber from 1 to N.
        select n, rownumber
        from
        (
            --Maximum number of rows needed (the largest number in the table)
            select level rownumber
            from dual
            connect by level <= (select max(n) from test1)
        ) max_rows
        cross join test1
        where max_rows.rownumber <= test1.n
        order by n, rownumber
    ) n_to_rows
    model
    partition by (n)
    dimension by (rownumber)
    measures (0 as coscos)
    (
        coscos[1] = cos(0),
        coscos[rownumber > 1] = cos(coscos[cv(rownumber)-1])
    )
)
where n = rownumber
order by n;

结果:

N   COSCOS
1   1
2   0.54030230586814
5   0.793480358742566
10  0.73140404242251

让神圣战争开始:

这个查询是否是一个好主意?我不会在生产环境中运行这个查询,但希望它能成为一个有用的示范,说明任何问题都可以通过SQL来解决。

我见过数千个小时被浪费,因为人们害怕使用SQL。如果你经常使用数据库,不使用SQL作为你的主要编程语言是愚蠢的。偶尔花几个小时来测试SQL的极限是很好的。一些奇怪的查询是避免感染许多数据库程序员的灾难性逐行处理思维方式所付出的小代价。


谢谢!我以前从未使用过模型子句。 - Egor Skriptunoff

1
使用 WITH FUNCTION(Oracle 12c):
WITH FUNCTION coscos(n INT) RETURN NUMBER IS
BEGIN
   IF n > 1 
     THEN RETURN cos(coscos(n-1));
     ELSE RETURN cos(0);   
   END IF;
END;
SELECT n, coscos(n)
FROM t;

db<>fiddle演示

输出:

+-----+-------------------------------------------+
| N   |                 COSCOS(N)                 |
+-----+-------------------------------------------+
|  1  |                                         1 |
|  2  | .5403023058681397174009366074429766037354 |
|  5  |  .793480358742565591826054230990284002387 |
| 10  | .7314040424225098582924268769524825209688 |
+-----+-------------------------------------------+

@MatthewMcPeak 是的,我完全意识到这一点。这个问题已经被修改了,这就是为什么我添加了我的答案。我们现在是2019年,Oracle 20c正在路上。 - Lukasz Szozda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接