There is no "recursion" here, and I think that you are confused here.
From the PostgreSQL documentation: http://www.postgresql.org/docs/9.4/static/queries-with.html
Note: Strictly speaking, this process is iteration not recursion, but RECURSIVE is the terminology chosen by the SQL standards committee.
To rephrase this sentence, WITH RECURSIVE can be thought of as a simple WHILE loop.
WITH RECURSIVE t(n) AS ( VALUES (1) UNION ALL SELECT n+1 FROM t WHERE n < 100 ) SELECT * FROM t;
Here are a few custom-made pseudo codes to explain this process in detail.
# Step 1: initialisation LET cte_result = EMPTY LET working_table = VALUES (1) LET intermediate_table = EMPTY
And using an example
# Step 1: initialisation cte_result: EMPTY | working_table: 1 | intermediate_table: EMPTY # Step 2: result initialisation cte_result: 1 | working_table: 1 | intermediate_table: EMPTY # Step 3: iteration test count(working_table) = 1 # OK # Step 4: iteration select cte_result: 1 | working_table: 1 | intermediate_table: 2 # Step 5: iteration merge cte_result: 1, 2 | working_table: 1 | intermediate_table: 2 # Step 6: iteration end cte_result: 1, 2 | working_table: 2 | intermediate_table: EMPTY # Step 3: iteration test count(working_table) = 1 # OK # Step 4: iteration select cte_result: 1, 2 | working_table: 2 | intermediate_table: 3 # Step 5: iteration merge cte_result: 1, 2, 3 | working_table: 2 | intermediate_table: 3 # Step 6: iteration end cte_result: 1, 2, 3 | working_table: 3 | intermediate_table: EMPTY # … 97 more iterations and you get this state cte_result: 1, 2, …, 100 | working_table: 100 | intermediate_table: EMPTY # Step 3: iteration test count(working_table) = 1 # OK # Step 4: iteration select, the iteration query does not return any rows due to the WHERE clause cte_result: 1, 2, …, 100 | working_table: 100 | intermediate_table: EMPTY # Step 5: iteration merge, nothing is merged into the cte_result cte_result: 1, 2, …, 100 | working_table: 100 | intermediate_table: EMPTY # Step 6: iteration end cte_result: 1, 2, …, 100 | working_table: EMPTY | intermediate_table: EMPTY # Step 3: iteration test count(working_table) = 0 # STOP # Step 7: return cte_result: 1, 2, …, 100
Thus, the result of CTE are all numbers from 1 to 100.