2016-06-17 3 views
0

Я читал с помощью запроса в Postgres. И это то, что меня поразилоВозможное объяснение на WITH RECURSIVE Query Postgres

WITH RECURSIVE t(n) AS (
    VALUES (1) 
    UNION ALL 
    SELECT n+1 FROM t WHERE n < 100 
) 
SELECT sum(n) FROM t; 

Я не могу понять, как работает оценка запроса.

  • t (n) это звучит как функция с параметром. как передается значение n.

Любое понимание того, как происходит разрыв рекурсивного оператора в SQL.

+0

http://stackoverflow.com/q/30015842/330315 –

ответ

3

Это называется общим выражением таблицы и способ выражения рекурсивного запроса в SQL:

t(n) определяет имя КТР, как t, с одной колонке под названием n. Это похоже на псевдоним для производной таблицы:

select ... 
from (
    ... 
) as t(n);

Рекурсии начинается со значением 1 (это values (1) части), а затем рекурсивно добавляет один к нему до тех пор, пока 99 будет достигнут. Таким образом, он генерирует числа от 1 до 99. Затем окончательный запрос суммирует все эти числа.

n - это имя столбца, не «переменная», а «назначение» происходит так же, как и любое извлечение данных.

WITH RECURSIVE t(n) AS (
    VALUES (1) --<< this is the recursion "root" 
    UNION ALL 
    SELECT n+1 FROM t WHERE n < 100 --<< this is the "recursive part" 
) 
SELECT sum(n) FROM t; 

Если вы «раскатать» рекурсию (который на самом деле является итерация), то вы бы ветер с чем-то вроде этого:

select x.n + 1 
from (
    select x.n + 1 
    from (
    select x.n + 1 
    from (
     select x.n + 1 
     from (
     values (1) 
    ) as x(n) 
    ) as x(n) 
) as x(n) 
) as x(n) 

более подробно в руководстве:
https://www.postgresql.org/docs/current/static/queries-with.html

+0

Я понимаю, что оператор SQL делает все, что я хочу знать, как работает оценка с тех пор. например, как значение n присваивается 1 (я знаю, что оно назначено VALUES (1), но как?) next the Union ALL на «VALUES (1) и SELECT n + 1 ...» Это просто, что он что традиционная функция рекурсии мы пишем на языке высокого уровня, например 'C' или' C++' – LivingColors

+0

Целью данного вопроса является понимание оценки. Чтобы я мог быть достаточно уверен, чтобы написать, если нужно. – LivingColors

+0

@LivingColors 'n' не является переменной. Это имя столбца. –

0

Если вы ищете, как это оценивается, рекурсия происходит в две фазы.

  1. Корень выполняется один раз.
  2. Рекурсивная часть выполняется до тех пор, пока не будут возвращены никакие строки. В этой связи документация немного расплывчата.

Теперь, как правило, в базах данных мы думаем о «функции» по-другому, чем мы думаем о них, когда мы требуем программирования. В терминах базы данных лучшим способом думать о функции является «соответствие, где для каждого значения домена у вас есть ровно одно соответствующее значение». Поэтому одной из ближайших задач является прекращение мышления с точки зрения функций программирования. Даже пользовательские функции лучше всего обдумать другим способом, так как это позволяет избежать большой потенциальной гадости в отношении пересечения работы с запросом и планировщиком запросов ... Таким образом, это может выглядеть как функция, но это неверно.

Вместо предложения 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 

Конечно, это упрощение, потому что внутренне мы отслеживаем КТР государства и сохранить присоединение к последней итерации, поэтому на практике они получают откинуть назад вблизи линейной сложность (в то время как приведенная выше диаграмма показала бы гораздо худшую производительность, чем эта).

Так что в реальности вы получите что-то подобное:

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 
... 

В сущности предыдущие значения переносятся.