Вы не можете ссылаться на столбец рекурсивно в его определении.
Однако вы можете express вычислить факториал как:
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 функция, называемая рекурсивным запросом, которую также можно использовать для express рекурсивной таблицы факториала:
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 не имеют операции агрегированного умножения, поэтому для выполнения операции агрегированного умножения сначала мы должны взять журнал каждого значения, затем можно использовать функцию суммирования, чтобы получить журнал регистрации значений. Это мы инвертируем с последним шагом возведения в степень.
Это работает, пока умножаемые значения положительны, поскольку log
не определено для 0 и отрицательных чисел. Если у вас отрицательные числа или ноль, уловка состоит в том, чтобы проверить, равно ли какое-либо значение 0, тогда вся совокупность равна 0, и проверить, является ли число отрицательных значений четным, тогда результат является положительным, иначе он отрицательный. Кроме того, вы также можете преобразовать реалы в комплексную плоскость, а затем использовать тождество 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}
что такое рекурсивный запрос
Рекурсивный запрос позволяет express рекурсивная логика c с использованием SQL. Рекурсивные запросы часто используются для генерации родительско-дочерних отношений из реляционных данных (например, отчет менеджера или иерархия классификации продуктов), но они обычно могут использоваться для запроса любой древовидной структуры.
Вот SO-ответ, который я недавно написал, который иллюстрирует и объясняет некоторые возможности рекурсивных запросов .
Существует также множество полезных руководств по рекурсивным запросам. Это очень мощная sql -языковая функция, которая решает тип проблемы, которую очень трудно обойтись без рекурсии.
Надеюсь, что это даст вам более полное представление о том, что делает код. Счастливого обучения!