我刚刚在PostgreSQL中发现了PostgreSQL,我一直在试验它能实现什么。我想我可以用它来计算阶乘,然后我写道
SELECT i, i * lag(factorial, 1, 1) OVER (ORDER BY i, 1) as factorial FROM generate_series(1, 10) as i;
但在线IDE抱怨42703 column "factorial" does not exist
。
有什么方法可以访问以前的延迟调用的结果吗?
发布于 2020-04-28 10:30:29
不能在列的定义中递归引用该列。
但是,您可以将阶乘计算表示为:
SELECT i, EXP(SUM(LN(i)) OVER w)::int factorial
FROM generate_series(1, 10) i
WINDOW w AS (ORDER BY i ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW);
-- outputs:
i | factorial
----+-----------
1 | 1
2 | 2
3 | 6
4 | 24
5 | 120
6 | 720
7 | 5040
8 | 40320
9 | 362880
10 | 3628800
(10 rows)
Postgresql确实支持名为递归查询的高级SQL特性,该特性还可用于递归地表示阶乘表:
WITH RECURSIVE series AS (
SELECT i FROM generate_series(1, 10) i
)
, rec AS (
SELECT i, 1 factorial FROM series WHERE i = 1
UNION ALL
SELECT series.i, series.i * rec.factorial
FROM series
JOIN rec ON series.i = rec.i + 1
)
SELECT *
FROM rec;
EXP(SUM(LN(i)) OVER w)
所做的:
这利用了数学特性:
[1]: log(a * b * c) = log (a) + log (b) + log (c)
[2]: exp (log a) = a
[combining 1&2]: exp(log a + log b + log c) = a * b * c
SQL没有聚合乘运算,因此要执行聚合乘运算,首先要获取每个值的日志,然后可以使用sum聚合函数给出值的乘积的日志。我们用最后的指数步骤进行反演。
只要被乘的值是正的,因为对于0和负数,log
是未定义的,这是有效的。如果你有负数,或者零,诀窍是检查是否有任何值是0,那么整个聚集值是0,并且检查负值的数目是否是偶数,结果是正的,否则它是负的。或者,您也可以将reals转换为复杂平面,然后使用标识Log(z) = ln(r) - iπ
。
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
做什么
这将声明一个展开的窗口框架,其中包括前面的所有行和当前行。
例如:
when i equals 1 the values in this window frame are {1}
when i equals 2 the values in this window frame are {1,2}
when i equals 3 the values in this window frame are {1,2,3}
什么是递归查询
递归查询允许您使用SQL表示递归逻辑。递归查询通常用于从关系数据(考虑管理器-报表或产品分类层次结构)生成父-子关系,但它们通常可以用于查询任何类似于树的结构。
下面是我写了一段时间的答案,它说明并解释了递归查询的一些功能。。
还有大量关于递归查询的有用教程。它是一种非常强大的sql语言特性,解决了一种非常困难的问题,不需要递归。
希望这能让您更深入地了解代码的功能。学习愉快!
https://stackoverflow.com/questions/61487283
复制相似问题