overview
A tree structure usually consists of a root node, a parent node (PID), a child node (ID) and a leaf node.
query syntax
SELECT [LEVEL],*
FROM table_name
START WITH 条件1
CONNECT BY PRIOR 条件2
WHERE 条件3
ORDER BY 排序字段
Description: LEVEL—pseudo-column, used to indicate the level of the tree (for the level of the query result, the level of the root node is 1)
Condition 1—the limiting condition of the root node, of course, the authority can also be relaxed to obtain multiple root nodes, That is to obtain multiple trees (ie: the condition after start with indicates where the recursion starts.)
Condition 2—the connection condition, the purpose is to give the relationship between the parent and the child, and perform recursive queries based on this relationship (ie: when recursive The two data before and after are connected by condition 2)
Condition 3—filter condition, to filter all returned records.
SortField - Sorts all returned records
prior use
The position of prior determines the specific relationship during recursion or determines the retrieval order during query. Prior field 1=field 2 can be understood as field 1 of the current node is equal to field 2 of the next node.
Two ways of writing:
connect by prior PID=ID means to use a top-down search method (find the parent node first and then find the child node)
connect by PID=prior ID means use a bottom-up search method (find the leaf node first and then find the parent node)
example
grammar:
select
from table name t
where filter condition
start with t.PID=xx --start root node
connect by prior t.ID=t.PID
SELECT t.JGBH
FROM GG_JGBH t
where SYBZ = 1
START WITH t.SJJG = (select SJJG from GG_JGBH where JGBH = '0001')
CONNECT BY PRIOR t.JGBH = t.SJJG
But the content of the upper-speed query does not include the data corresponding to the "start root node". At this time, my solution is to use OR to associate
select E_ADDRESS.*, (select jgmc from gg_jgbh where jgbh = account) jgmc
from E_ADDRESS
where ACCOUNT = (select SJJG from GG_JGBH where JGBH = '0001')
or ACCOUNT in
(SELECT t.JGBH
FROM GG_JGBH t
where SYBZ = 1
START WITH t.SJJG = (select SJJG from GG_JGBH where JGBH = '0001')
CONNECT BY PRIOR t.JGBH = t.SJJG)
example code
1. Query all descendant nodes under a node (including parent nodes at all levels)
// 查询id为101的所有后代节点,包含101在内的各级父节点
select t.* from SYS_ORG t start with id = '101' connect by parent_id = prior id
2. Query all descendant nodes under a node (excluding parent nodes at all levels)
select t.*
from SYS_ORG t
where not exists (select 1 from SYS_ORG s where s.parent_id = t.id)
start with id = '101'
connect by parent_id = prior id
3. Query all parent nodes of a node (all ancestor nodes , including yourself )
select t.*
from SYS_ORG t
start with id = '401000501'
connect by prior parent_id = id
4. Query all sibling nodes (brothers) of a node
select * from SYS_ORG t
where exists (select * from SYS_ORG s where t.parent_id=s.parent_id and s.id='401000501')
5. Query all sibling nodes (family nodes) of a node, assuming no level field is set
Two techniques are used here, one is to use level to identify the level of each node in the table, and the other is to use the with syntax to simulate a temporary table with levels
with tmp as(
select t.*, level leaf
from SYS_ORG t
start with t.parent_id = '0'
connect by t.parent_id = prior t.id)
select *
from tmp
where leaf = (select leaf from tmp where id = '401000501');
6. Query the parent node of a node and the parent's brother node (uncle node)
The query here is divided into the following steps.
First, use a temporary table plus a level for the entire table;
second, there are several types based on the level. For the example above, there are three situations:
(1) The current node is the top-level node, that is, the lev that is queried If the value is 1, then it has no parent node and will not be considered.
(2) The current node is a level 2 node, and the lev value obtained from the query is 2, so it is only necessary to ensure that the lev level is 1 is the sibling node of its superior node.
(3) In other cases, if the level is 3 or above, then the superior node (grandfather) of the superior node must be selected and found out, and then it is judged that the subordinate nodes of the grandfather are all sibling nodes belonging to the superior node of the node.
Finally, use union to combine the query results to form a result set.
with tmp as(
select t.*, level lev
from SYS_ORG t
start with t.parent_id = '0'
connect by t.parent_id = prior t.id)
select b.*
from tmp b,(select *
from tmp
where id = '401000501' and lev = '2') a
where b.lev = '1'
union all
select *
from tmp
where parent_id = (select distinct x.id
from tmp x, --祖父
tmp y, --父亲
(select *
from tmp
where id = '401000501' and lev > '2') z --儿子
where y.id = z.parent_id and x.id = y.parent_id);