16.10 - Recursive Queries - Teradata Database

Teradata Database SQL Fundamentals

Product
Teradata Database
Release Number
16.10
Published
June 2017
Content Type
Programming Reference
Publication ID
B035-1141-161K
Language
English (United States)
Last Update
2018-04-25

A recursive query is a way to query hierarchies of data, such as an organizational structure, bill-of-materials, and document hierarchy.

Recursion is typically characterized by three steps:
  1. Initialization
  2. Recursion, or repeated iteration of the logic through the hierarchy
  3. Termination
Similarly, a recursive query has three execution phases:
  1. Create an initial result set.
  2. Recursion based on the existing result set.
  3. Final query to return the final result set.

Specifying a Recursive Query

You can specify a recursive query by:
  • Preceding a query with the WITH RECURSIVE clause
  • Creating a view using the RECURSIVE clause in a CREATE VIEW statement

Example: Using the WITH RECURSIVE Clause

Consider the following employee table:

   CREATE TABLE employee
      (employee_number INTEGER
      ,manager_employee_number INTEGER
      ,last_name CHAR(20)
      ,first_name VARCHAR(30));

The table represents an organizational structure containing a hierarchy of employee-manager data.

The following figure depicts what the employee table looks like hierarchically.

The following recursive query retrieves the employee numbers of all employees who directly or indirectly report to the manager with employee_number 801:

   WITH RECURSIVE temp_table (employee_number) AS
   ( SELECT root.employee_number
     FROM employee root
     WHERE root.manager_employee_number = 801
   UNION ALL
     SELECT indirect.employee_number
     FROM temp_table direct, employee indirect
     WHERE direct.employee_number = indirect.manager_employee_number
   )
   SELECT * FROM temp_table ORDER BY employee_number;

In the example, temp_table is a temporary named result set that can be referred to in the FROM clause of the recursive statement.

The initial result set is established in temp_table by the nonrecursive, or seed, statement and contains the employees that report directly to the manager with an employee_number of 801:

   SELECT root.employee_number
   FROM employee root
   WHERE root.manager_employee_number = 801

The recursion takes place by joining each employee in temp_table with employees who report to the employees in temp_table. The UNION ALL adds the results to temp_table.

  SELECT indirect.employee_number
  FROM temp_table direct, employee indirect
  WHERE direct.employee_number = indirect.manager_employee_number

Recursion stops when no new rows are added to temp_table.

The final query is not part of the recursive WITH clause and extracts the employee information out of temp_table:

   SELECT * FROM temp_table ORDER BY employee_number;

Here are the results of the recursive query:

employee_number
---------------
1001
1002
1003
1004
1006
1008
1010
1011
1012
1014
1015
1016
1019

Using the RECURSIVE Clause in a CREATE VIEW Statement

Creating a view using the RECURSIVE clause is similar to preceding a query with the WITH RECURSIVE clause.

Consider the employee table that was presented in the previous example. The following statement creates a view named hierarchy_801 using a recursive query that retrieves the employee numbers of all employees who directly or indirectly report to the manager with employee_number 801:

   CREATE RECURSIVE VIEW hierarchy_801 (employee_number) AS
   ( SELECT root.employee_number
     FROM employee root
     WHERE root.manager_employee_number = 801
   UNION ALL
     SELECT indirect.employee_number
     FROM hierarchy_801 direct, employee indirect
     WHERE direct.employee_number = indirect.manager_employee_number
   );

The seed statement and recursive statement in the view definition are the same as the seed statement and recursive statement in the previous recursive query that uses the WITH RECURSIVE clause, except that the hierarchy_801 view name is different from the temp_table temporary result name.

To extract the employee information, use the following SELECT statement on the 
hierarchy_801 view:

   SELECT * FROM hierarchy_801 ORDER BY employee_number;

Here are the results:

employee_number
---------------
1001
1002
1003
1004
1006
1008
1010
1011
1012
1014
1015
1016
1019

Depth Control to Avoid Infinite Recursion

If the hierarchy is cyclic, or if the recursive statement specifies a bad join condition, a recursive query can produce a runaway query that never completes with a finite result. The best practice is to control the depth of the recursion:

  • Specify a depth control column in the column list of the WITH RECURSIVE clause or recursive view
  • Initialize the column value to 0 in the seed statements
  • Increment the column value by 1 in the recursive statements
  • Specify a limit for the value of the depth control column in the join condition of the recursive statements

Here is an example that modifies the previous recursive query that uses the WITH RECURSIVE clause of the employee table to limit the depth of the recursion to five cycles:

   WITH RECURSIVE temp_table (employee_number, depth) AS
   ( SELECT root.employee_number, 0 AS depth
     FROM employee root
     WHERE root.manager_employee_number = 801
   UNION ALL
     SELECT indirect.employee_number, direct.depth+1 AS newdepth
     FROM temp_table direct, employee indirect
     WHERE direct.employee_number = indirect.manager_employee_number
     AND newdepth <= 5
   )
   SELECT * FROM temp_table ORDER BY employee_number;

Related Topics

For more information about:
  • Recursive queries, see “WITH RECURSIVE” in SQL Data Manipulation Language , B035-1146 .
  • Recursive views, see “CREATE VIEW” in SQL Data Definition Language - Syntax and Examples, B035-1144.