Oracle SQL 中的 START WITH 和 CONNECT BY 条件

Sab*_*tra 3 oracle oracle-12c

我对 START WITH 和 CONNECT BY 条件有疑问(在 Oracle 12c 中):

这是我的 Oracle SQL:

SELECT 
    employee_id, 
    lpad(' ', level*2-1,' ') || last_name, 
    manager_id, 
    level,
    SYS_CONNECT_BY_PATH(last_name, '/') "Path" --returns the full path of the child
FROM 
    hr.employees
start with employee_id = 100
CONNECT BY PRIOR employee_id = manager_id 
AND NOT (last_name = 'Cambrault' and first_name = 'Gerald')
order siblings by last_name
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

EMPLOYEE_ID     LAST_NAME           MANAGER_ID  LEVEL   PATH
100             King                    null    1   /King
102                 De Haan             100     2   /King/De Haan
103                     Hunold          102     3   /King/De Haan/Hunold
105                         Austin      103     4   /King/De Haan/Hunold/Austin
104                         Ernst       103     4   /King/De Haan/Hunold/Ernst
107                         Lorentz     103     4   /King/De Haan/Hunold/Lorentz
106                         Pataballa   103     4   /King/De Haan/Hunold/Pataballa
Run Code Online (Sandbox Code Playgroud)

但是当我删除上面查询中的 START WITH 时:

SELECT 
    employee_id, 
    lpad(' ', level*2-1,' ') || last_name, 
    manager_id, 
    level,
    SYS_CONNECT_BY_PATH(last_name, '/') "Path" --returns the full path of the child
FROM 
    hr.employees
CONNECT BY PRIOR employee_id = manager_id 
AND NOT (last_name = 'Cambrault' and first_name = 'Gerald')
order siblings by last_name
Run Code Online (Sandbox Code Playgroud)

它给出以下结果:

EMPLOYEE_ID     LAST_NAME   MANAGER_ID  LEVEL   PATH
148             Cambrault   100         1       /Cambrault
172                 Bates   148         2       /Cambrault/Bates
169                 Bloom   148         2       /Cambrault/Bloom
170                 Fox     148         2       /Cambrault/Fox
173                 Kumar   148         2       /Cambrault/Kumar
168                 Ozer    148         2       /Cambrault/Ozer
171                 Smith   148         2       /Cambrault/Smith
Run Code Online (Sandbox Code Playgroud)

您能否解释一下为什么尽管使用条件 NOT (last_name = 'Cambrault' 和 first_name = 'Gerald') 但它没有任何效果,而它仅在与 START WITH 一起使用时才起作用(从 employee_id = 100 开始层次结构)。我了解 CONNECT BY 中的条件对根行没有影响,但employee_id (148) 不是根;它只是一个父行,为什么它不起作用?

ype*_*eᵀᴹ 5

当你有CONNECT BY没有START WITH, the root, starting points of the recursion are all the rows of the table. It is useful if you want to find all the hierarchies under all employees.

CONNECT BY仅针对下一级递归检查in 的条件,因此仅针对兄弟姐妹。

您可以修改START WITH以获取除 Cambrault 之外的所有内容:(
请注意,这样,一名员工可能会出现多次,一次作为个人,一次作为其经理的孩子,另一次作为其经理的孩子,另一次作为其经理的经理的孙子等等
(所以这可能不是你想要的):

START WITH 
      NOT (last_name = 'Cambrault' AND first_name = 'Gerald')
Run Code Online (Sandbox Code Playgroud)

或顶级经理(没有经理的雇主)下的所有层次结构。每个人都会这样出现一次:

START WITH manager_id IS NULL
Run Code Online (Sandbox Code Playgroud)

或顶级经理(没有经理的雇主)下的所有层次结构,除了康布罗特的。
请注意,这将为您提供与之前使用当前数据相同的结果START WITH(但当 Cambrault 晋升为顶级经理时会有所不同):

START WITH manager_id IS NULL
  AND NOT (last_name = 'Cambrault' AND first_name = 'Gerald')
Run Code Online (Sandbox Code Playgroud)

dbfiddle.uk进行测试。