Hierarchical Queries
If a table contains hierarchical data, then you can select rows in a hierarchical order using the hierarchical query clause:
Text description of hierarchical_query_clause:
[START WITH condition] CONNECT BY condition
- START WITH specifies the root row(s) of the hierarchy.
- CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy. In a hierarchical query, one expression in condition must be qualified with the PRIOR operator to refer to the parent row. For example,
If the CONNECT BY condition is compound, then only one condition requires the PRIOR operator. For example:
CONNECT BY last_name != 'King' AND PRIOR employee_id = manager_id
In addition, the CONNECT BY condition cannot contain a subquery.
PRIOR is a unary operator and has the same precedence as the unary + and - arithmetic operators. It evaluates the immediately following expression for the parent row of the current row in a hierarchical query.
PRIOR is most commonly used when comparing column values with the equality operator. (The PRIOR keyword can be on either side of the operator.) PRIOR causes Oracle to use the value of the parent row in the column. Operators other than the equal sign (=) are theoretically possible in CONNECT BY clauses. However, the conditions created by these other operators can result in an infinite loop through the possible combinations. In this case Oracle detects the loop at run time and returns an error.
The manner in which Oracle processes a WHERE clause (if any) in a hierarchical query depends on whether the WHERE clause contains a join:
- If the WHERE predicate contains a join, Oracle applies the join predicates before doing the CONNECT BY processing.
- If the WHERE clause does not contain a join, Oracle applies all predicates other than the CONNECT BY predicates after doing the CONNECT BY processing without affecting the other rows of the hierarchy.
Oracle uses the information from the hierarchical query clause to form the hierarchy using the following steps:
- Oracle processes the WHERE clause either before or after the CONNECT BY clause depending on whether the WHERE clause contains any join predicates (as described in the preceding bullet list).
- Oracle selects the child rows of each root row. Each child row must satisfy the condition of the CONNECT BY condition with respect to one of the root rows.
- Oracle selects successive generations of child rows. Oracle first selects the children of the rows returned in step 3, and then the children of those children, and so on. Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row.
- If the query contains a WHERE clause without a join, then Oracle eliminates all rows from the hierarchy that do not satisfy the condition of the WHERE clause. Oracle evaluates this condition for each row individually, rather than removing all the children of a row that does not satisfy the condition.
- Oracle returns the rows in the order shown in Figure below. In the diagram, children appear below their parents.
To find the children of a parent row, Oracle evaluates the PRIOR expression of the CONNECT BY condition for the parent row and the other expression for each row in the table. Rows for which the condition is true are the children of the parent. The CONNECT BY condition can contain other conditions to further filter the rows selected by the query. The CONNECT BY condition cannot contain a subquery.
If the CONNECT BY condition results in a loop in the hierarchy, then Oracle returns an error. A loop occurs if one row is both the parent (or grandparent or direct ancestor) and a child (or a grandchild or a direct descendent) of another row.
例子:
如有表TU_HIER
有两个列col_sub和col_parent,分别代表子节点和父节点
select * from TU_HIER
--where col_sub <> '002'
CONNECTBYcol_parent = PRIORcol_sub
--and col_sub <> '002'
startwithcol_sub = '001'
ORDERSIBLINGSBYcol_sub
需要注意的是
CONNECT BY中的筛选条件会立即生效,并影响其子树的生成,如col_sub<> '002',则以002为根的整棵子树都会被去除,不会出现在查询结果中。
而Where中的筛选条件会等到所有连接都完成,再对最终的结果集统一进行筛选,如where col_sub <> '002',则只有002会被去除,而以002为根节点的其他子节点不会被去除。
order siblings by在默认排序基础上对兄弟节点进行进一步排序。