with tutorial the framework español djangoproject applications database postgresql recursion recursive-query with-statement

database - tutorial - the django project



¿Cómo se interpreta sql with-recursive statement? (1)

No hay "recursión" aquí y creo que aquí es donde te confundes.

De la documentación de PostgreSQL: 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.

Parafraseando esta oración, un WITH RECURSIVE se puede ver como un simple bucle WHILE .

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

Aquí hay un pseudocódigo hecho a medida para explicar este proceso en detalle

# Step 1: initialisation LET cte_result = EMPTY LET working_table = VALUES (1) LET intermediate_table = EMPTY # Step 2: result initialisation, merge initialisation into cte_result cte_result = cte_result UNION working_table # Step 3: iteration test WHILE (working_table is not empty) DO # Step 4: iteration select, we substitute the self-reference with working_table intermediate_table = SELECT n+1 FROM working_table WHERE n < 100 # Step 5: iteration merge, merge the iteration result into cte_result cte_result = cte_result UNION intermediate_table # Step 6: iteration end, prepare for next iteration working_table = intermediate_table intermediate_table = EMPTY END WHILE # Step 7: return RETURN cte_result

Y usando un ejemplo

# 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

Entonces, el resultado del CTE es todos los números del 1 al 100.

Me gustaría pedir ayuda para entender cómo funciona "con recursivo". Más precisamente, POR QUÉ la consulta de ancla (el término no recursivo) no se replica en la subllamada del CTE. Hice mi mejor esfuerzo para comprenderlo solo, pero no estoy seguro.

Antes que nada tomemos el ejemplo de PostgreSQL que es el más simple que encontré (haga la suma de 1 a 100):

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

Mi código paso a paso (utilicé enlaces a continuación):

  1. Evalúa el término no recursivo. Para la UNIÓN [...].

    Incluya todas las filas restantes en el resultado de la consulta recursiva y también colóquelas en una tabla de trabajo temporal.

  2. Siempre que la tabla de trabajo no esté vacía , repita estos pasos:

    • Evalúe el término recursivo, sustituyendo los contenidos actuales de la tabla de trabajo por la autorreferencia recursiva. Para la UNIÓN [...]. Incluya todas las filas restantes en el resultado de la consulta recursiva y también colóquelas en una tabla intermedia temporal.

    • Reemplace el contenido de la mesa de trabajo con el contenido de la mesa intermedia, luego vacíe la mesa intermedia ".

LVL 0:

  1. parte no recursiva

    • CTE: (N) 1
    • TABLA DE TRABAJO: (N) 1
  2. parte recursiva

    • CTE: (N) 1
    • TABLA DE TRABAJO: (N) 1
    • TABLA INTERMEDIA (N) 2

(Esta es la parte en la que lío, creo) - sustitución de la TABLA DE TRABAJO

Entonces la t recursiva usará la TABLA DE TRABAJO para hacer SELECCIONAR n + 1 y colocar el resultado en TABLA INTERMEDIA.

  1. UNION ALL

    • CTE: (N) 1 2
    • TABLA DE TRABAJO: (N) 2
    • TABLA INTERMEDIA: LIMPIO
  2. Luego pasamos al siguiente nivel por la llamada de t ¿verdad? (porque la condición END WHERE n <100 = FALSE)

LVL 1:

Sabemos que coz postgreSQL lo dice "Mientras la tabla de trabajo no esté vacía, repita los pasos recursivos" Entonces repetirá los pasos 2. y 3. (si estoy en lo correcto) hasta la condición END luego haga SUM.

PERO si me limito a seguir la llamada de la próxima letra de t, ¿no deberíamos hacer VALORES (1) primero?

Estoy realmente confundido acerca de cómo es posible.

Saludos cordiales, Falt4rm