分層查詢(Hierarachical Queries)(翻譯)

翻譯自oracle 官網中的Hierarchical Queries
網址:https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm#i2060615
大家可以過去看英文版

如果一張表中存儲着分層(樹狀)數據,那麼你就可以使用分層查詢語句以分層(樹狀)順序來進行查詢

分層查詢語句的語法:
hierarchical_query_clause

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

通過 僞列LEVELCONNECT_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子句的關鍵字學習到更多信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章