Если вы ищете, как это оценивается, рекурсия происходит в два этапа.
- Корень выполняется один раз.
- Рекурсивная часть выполняется до тех пор, пока не будут возвращены строки. Документация немного расплывчата в этом вопросе.
Теперь, обычно в базах данных, мы думаем о «функции» иначе, чем мы думаем о них, когда занимаемся императивным программированием. В терминах базы данных лучший способ думать о функции — это «соответствие, в котором для каждого значения домена у вас есть ровно одно соответствующее значение». Так что одна из неотложных задач — перестать думать в терминах функций программирования. Даже пользовательские функции лучше рассматривать с другой точки зрения, поскольку это позволяет избежать многих потенциальных неприятностей, связанных с пересечением выполнения запроса и планировщика запросов... Таким образом, это может выглядеть как функция, но это неверно.
Вместо этого в предложении WITH используется другая, почти обратная запись. Здесь у вас есть имя набора t
, за которым следует (необязательно в этом случае) структура кортежа (n)
. Так что это не функция с параметром, а отношение со структурой.
Итак, как это ломается:
SELECT 1 as n where n < 100
UNION ALL
SELECT n + 1 FROM (SELECT 1 as n) where n < 100
UNION ALL
SELECT n + 1 FROM (SELECT n + 1 FROM (SELECT 1 as n)) where n < 100
Конечно, это упрощение, потому что внутренне мы отслеживаем состояние cte и продолжаем объединяться с последней итерацией, поэтому на практике они сводятся к почти линейной сложности (в то время как приведенная выше диаграмма предполагает гораздо худшую производительность).
Итак, на самом деле вы получаете что-то вроде:
SELECT 1 as n where 1 < 100
UNION ALL
SELECT 1 + 1 as n where 1 + 1 < 100
UNION ALL
SELECT 2 + 1 AS n WHERE 2 + 1 < 100
...
По сути, предыдущие значения сохраняются.
17.06.2016
VALUES(1) and SELECT n+1 ...
Просто это сильно отличается от того, как традиционная функция рекурсии мы пишем в высоком конце язык, напримерC
илиC++
17.06.2016n
не является переменной. Это имя столбца. 17.06.2016Evaluate the non-recursive term. For UNION (but not UNION ALL), discard duplicate rows. Include all remaining rows in the result of the recursive query, and also place them in a temporary working table.
. Можете ли вы помочь мне понять, что такое рекурсивный термин в приведенном выше примере. Я не могу понять, какая часть оператора вызывает рекурсию. 17.06.2016values(1)
— это нерекурсивная часть (она же корень). Выбор послеunion all
является рекурсивной частью (поскольку он ссылается/присоединяется к CTE (с именемt
) 17.06.2016select x.n + 1 from ( values (1) ) as x(n)
добавляет столбец «2» во временную таблицу, в которой его еще нет? 10.06.2019