A recursive query is a way to query hierarchies of data, such as an organizational structure, bill of materials, and document hierarchy.
- Initialization
- Recursion, or repeated iteration of the logic through the hierarchy
- Termination
- Create an initial result set.
- Recursion based on the existing result set.
- Final query to return the final result set.
Specifying a Recursive Query
- 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
- 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
- Recursive queries, see “WITH RECURSIVE” in Teradata Vantage™ - SQL Data Manipulation Language, B035-1146.
- Recursive views, see “CREATE VIEW” in Teradata Vantage™ - SQL Data Definition Language Syntax and Examples, B035-1144.