翻譯自oracle 官網中的Hierarchical Queries
網址:https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm#i2060615
大家可以過去看英文版
如果一張表中存儲着分層(樹狀)數據,那麼你就可以使用分層查詢語句以分層(樹狀)順序來進行查詢
分層查詢語句的語法:
START WITH:分層(樹狀)數據中的根節點
CONNECT BY:分層(樹狀)數據中父節點與子節點的特殊聯繫
The NOCYCLE parameter instructs Oracle Database to return rows from a query even if a CONNECT BY LOOP exists in the data. Use this
parameter along with the CONNECT_BY_ISCYCLE pseudocolumn to see which
rows contain the loop. Please refer to CONNECT_BY_ISCYCLE Pseudocolumn for more information.
- 翻譯:當在數據中存在以(connect by loop)爲條件查詢到結果時,那麼關鍵字(nocycle)(非循環關鍵字)將會通知oracle數據庫從集合中返回這些行。使用參數connect_by_iscycle來查看在循環結果中包含哪些行。
In a hierarchical query, one expression in condition must be qualified with the PRIOR operator to refer to the parent row. For example
- 翻譯:在層次(樹狀)查詢時,條件中的表達式必須存在用於指代雙親節點(父行/父節點)合適的條件(prior),例如
... PRIOR expr = expr
or
... expr = PRIOR expr
If the CONNECT BY condition is compound, then only one condition
requires the PRIOR operator, although you can have multiple PRIOR
conditions. For example:
如果連接條件(CONNECT BY)是多個的,那麼僅需要在連接條件中包含一個前置(PRIOR)條件就可以,當然你也可以使用多條前置(PRIOR)條件,例如
CONNECT BY last_name != 'King' AND PRIOR employee_id = manager_id ...
CONNECT BY PRIOR employee_id = manager_id and
PRIOR account_mgr_id = customer_id
...
prior是一個一元操作符,它擁有和算數運算符‘+’和‘-’一樣的優先級,在分層查詢中它指代當前行的雙親(父)節點。
prior經常用在比較兩列的值是否相等的操作中,(該關鍵字prior可以放在等式的兩端)。有了prior,在oracle中就可以使用該列中父節點的值。在CONNECT BY 子句中也可以用除了 = 號之外的其他操作符,不過這些操作符可能導致無限循環的結果,在這種情況下oracle會發現循環超時並返回錯誤信息。
Both the CONNECT BY condition and the PRIOR expression can take
the form of an uncorrelated subquery. However, the PRIOR expression
cannot refer to a sequence. That is, CURRVAL and NEXTVAL are not valid
PRIOR expressions。
CONNECT BY 條件和PRIOR表達式可以被用在無關子查詢中。但是,PRIOR表達式不能存在表示前後順序的關鍵詞,就是說不能使用比如前一個(CURRVAL)和後一個(NEXTVAL)的表示。
You can further refine a hierarchical query by using the
CONNECT_BY_ROOT operator to qualify a column in the select list. This
operator extends the functionality of the CONNECT BY [PRIOR] condition
of hierarchical queries by returning not only the immediate parent row
but all ancestor rows in the hierarchy.
你可以通過CONNECT_BY_ROOT操作符詳細的獲取查詢結果列表中特定的列,這個操作符擴大的了CONNECT BY [PRIOR]函數的查詢結果不僅會返回當前行的雙親節點同時也會返回樹狀(層狀)模型中的祖先節點。
分層查詢的圖形表示
此處建議回顧一下,深度優先算法
HIERARACHICAL QUERY EXAMPLE
CONNECT BY 例子
The following hierarchical query uses the CONNECT BY clause to define
the relationship between employees and managers:
下面的分層查詢通過使用CONNECT BY 子句,來說明僱員和管理者之間的關係。
SELECT employee_id, last_name, manager_id
FROM employees
CONNECT BY PRIOR employee_id = manager_id;
EMPLOYEE_ID LAST_NAME MANAGER_ID
----------- ------------------------- ----------
101 Kochhar 100
108 Greenberg 101
109 Faviet 108
110 Chen 108
111 Sciarra 108
112 Urman 108
113 Popp 108
200 Whalen 101
...
LEVEL例子
The next example is similar to the preceding example, but uses the
LEVEL pseudocolumn to show parent and child rows:
相似的例子,不過通過使用僞列LEVEL來展示雙親節點和孩子節點的關係。
SELECT employee_id, last_name, manager_id, LEVEL
FROM employees
CONNECT BY PRIOR employee_id = manager_id;
EMPLOYEE_ID LAST_NAME MANAGER_ID LEVEL
----------- ------------------------- ---------- ----------
101 Kochhar 100 1
108 Greenberg 101 2
109 Faviet 108 3
110 Chen 108 3
111 Sciarra 108 3
112 Urman 108 3
113 Popp 108 3
...
START WITH 例子
The next example adds a START WITH clause to specify a root row for the hierarchy and an ORDER BY clause using the SIBLINGS keyword to preserve ordering within the hierarchy:
下面的例子添加了一個START WITH子句來指明一個根節點,同時使用ORDER SLBLINGS BY子句在保持分層順序不變的情況下(將同屬一個雙親節點的兄弟節點按順序排列)。
SELECT last_name, employee_id, manager_id, LEVEL
FROM employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name;
LAST_NAME EMPLOYEE_ID MANAGER_ID LEVEL
------------------------- ----------- ---------- ----------
King 100 1
Cambrault 148 100 2
Bates 172 148 3
Bloom 169 148 3
Fox 170 148 3
Kumar 173 148 3
Ozer 168 148 3
Smith 171 148 3
De Haan 102 100 2
Hunold 103 102 3
Austin 105 103 4
Ernst 104 103 4
Lorentz 107 103 4
Pataballa 106 103 4
Errazuriz 147 100 2
Ande 166 147 3
Banda 167 147 3
...
In the hr.employees table, the employee Steven King is the head of the
company and has no manager. Among his employees is John Russell, who
is the manager of department 80. If we update the employees table to
set Russell as King’s manager, we will create a loop in the data:
屬於用戶hr的僱員表(hr.employees),Steven King是公司的BOSS,沒有上司(管理者),他的僱員中John Russell是80部門的經理。如果我們把僱員表中Steven King的上司設爲Russell,然後編寫下面循環代碼(要報錯了!要報錯了!要報錯了!)
UPDATE employees SET manager_id = 145
WHERE employee_id = 100;
SELECT last_name "Employee",
LEVEL, SYS_CONNECT_BY_PATH(last_name, '/') "Path"
FROM employees
WHERE level <= 3 AND department_id = 80
START WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id AND LEVEL <= 4;
2 3 4 5 6 7 ERROR:
ORA-01436: CONNECT BY loop in user data
The NOCYCLE parameter in the CONNECT BY condition causes Oracle to
return the rows in spite of the loop. The CONNECT_BY_ISCYCLE
pseudocolumn shows you which rows contain the cycle:
在CONNECT BY條件中使用非循環(NOCYCLE)參數使用oracle返回的行出現惡性循環,可以通過僞列CONNECT_BY_ISCYCLE指出你的那個行包含在這個惡性循環中(值爲1是惡性循環的原因)。
SELECT last_name "Employee", CONNECT_BY_ISCYCLE "Cycle",
LEVEL, SYS_CONNECT_BY_PATH(last_name, '/') "Path"
FROM employees
WHERE level <= 3 AND department_id = 80
START WITH last_name = 'King'
CONNECT BY NOCYCLE PRIOR employee_id = manager_id AND LEVEL <= 4;
Employee Cycle LEVEL Path
------------------------- ------ ------ -------------------------
Russell 1 2 /King/Russell
Tucker 0 3 /King/Russell/Tucker
Bernstein 0 3 /King/Russell/Bernstein
Hall 0 3 /King/Russell/Hall
Olsen 0 3 /King/Russell/Olsen
Cambrault 0 3 /King/Russell/Cambrault
Tuvault 0 3 /King/Russell/Tuvault
Partners 0 2 /King/Partners
King 0 3 /King/Partners/King
Sully 0 3 /King/Partners/Sully
McEwen 0 3 /King/Partners/McEwen
...
CONNECT_BY_ROOT 例子
The following example returns the last name of each employee in
department 110, each manager above that employee in the hierarchy, the number of levels between manager and employee, and the path between the two:
下面的例子返回在部門110中所有僱員的姓名,在分層中每個僱員上面的是管理者,展示經理和職員之間級別差數已經兩者之間的關係路徑
SELECT last_name "Employee", CONNECT_BY_ROOT last_name "Manager",
LEVEL-1 "Pathlen", SYS_CONNECT_BY_PATH(last_name, '/') "Path"
FROM employees
WHERE LEVEL > 1 and department_id = 110
CONNECT BY PRIOR employee_id = manager_id;
Employee Manager Pathlen Path
--------------- ------------ ---------- -----------------------------------
Higgins Kochhar 1 /Kochhar/Higgins
Gietz Kochhar 2 /Kochhar/Higgins/Gietz
Gietz Higgins 1 /Higgins/Gietz
Higgins King 2 /King/Kochhar/Higgins
Gietz King 3 /King/Kochhar/Higgins/Gietz
The following example uses a GROUP BY clause to return the total salary of each employee in department 110 and all employees below that employee in the hierarchy:
下面的例子使用GROUP BY子句,返回在部門110中每一個職員的總薪水同時顯示層級中該職員下的所有職員。
SELECT name, SUM(salary) "Total_Salary" FROM (
SELECT CONNECT_BY_ROOT last_name as name, Salary
FROM employees
WHERE department_id = 110
CONNECT BY PRIOR employee_id = manager_id)
GROUP BY name;
NAME Total_Salary
------------------------- ------------
Gietz 8300
Higgins 20300
King 20300
Kochhar 20300
可以學習下——這些我都還沒翻譯-哈哈-等我翻譯過會說明。
LEVEL Pseudocolumn and CONNECT_BY_ISCYCLE Pseudocolumn for a
discussion of how these pseudocolumns operate in a hierarchical query
通過 僞列LEVEL 和CONNECT_BY_ISCYCLE的練習,討論在分層查詢中如何使用僞列操作。
SYS_CONNECT_BY_PATH for information on retrieving the path of column
values from root to node
通過SYS_CONNECT_BY_PATH檢索從根節點到子節點(葉子)的路徑
order_by_clause for more information on the SIBLINGS keyword of ORDER
BY clauses
ORDER SIBLINGS BY,通過ORDRE BY子句的關鍵字學習到更多信息。