如何使用分层查询获取与条件匹配的行
How to get rows matching a condition using a hierarchical query
考虑 Oracle 文档中的以下查询 https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
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
我想过滤此树以获取姓氏中仅包含字母 'a' 的员工。
我可以使用 WHERE 子句,但问题是我不想只获取匹配条件的行,如果不匹配,我也不想获取它们的父事件,即我不想破坏一棵树。根据文档,Oracle 会单独评估每一行的条件。例如,如果我使用 WHERE 子句,我会得到 ID 为 101、109、111、112、200 的行。但我想得到 101、108、109、111、112、200。
如何在不破坏树的情况下过滤树?
作为其中一种方法,您可以开始自下而上遍历树 - 您会在 his/her 中找到一个名字为 a
的员工,然后沿着树往上走:
Distinct
子句用于去除重复的父项,我们需要第二个 connect by
子句来颠倒树。
-- sample of data from your question
with t1(EMPLOYEE_ID,LAST_NAME,MANAGER_ID) as(
select 101, 'Kochhar' , 100 from dual union all
select 108, 'Greenberg' , 101 from dual union all
select 109, 'Faviet' , 108 from dual union all
select 110, 'Chen' , 108 from dual union all
select 111, 'Sciarra' , 108 from dual union all
select 112, 'Urman' , 108 from dual union all
select 113, 'Popp' , 108 from dual union all
select 200, 'Whalen' , 101 from dual
)
-- actual query
select employee_id
, manager_id
, concat(lpad('-', 3*level, '-'), last_name) as last_name
from (
-- using distinct to get rid of duplicate parents
select distinct last_name
, employee_id
, manager_id
from t1
start with last_name like '%a%'
connect by employee_id = prior manager_id
) q
start with manager_id = 100
connect by prior employee_id = manager_id
结果:
EMPLOYEE_ID MANAGER_ID LAST_NAME
----------- ---------- --------------------
101 100 ---Kochhar
108 101 ------Greenberg
109 108 ---------Faviet
111 108 ---------Sciarra
112 108 ---------Urman
200 101 ------Whalen
6 rows selected.
考虑 Oracle 文档中的以下查询 https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
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
我想过滤此树以获取姓氏中仅包含字母 'a' 的员工。 我可以使用 WHERE 子句,但问题是我不想只获取匹配条件的行,如果不匹配,我也不想获取它们的父事件,即我不想破坏一棵树。根据文档,Oracle 会单独评估每一行的条件。例如,如果我使用 WHERE 子句,我会得到 ID 为 101、109、111、112、200 的行。但我想得到 101、108、109、111、112、200。 如何在不破坏树的情况下过滤树?
作为其中一种方法,您可以开始自下而上遍历树 - 您会在 his/her 中找到一个名字为 a
的员工,然后沿着树往上走:
Distinct
子句用于去除重复的父项,我们需要第二个 connect by
子句来颠倒树。
-- sample of data from your question
with t1(EMPLOYEE_ID,LAST_NAME,MANAGER_ID) as(
select 101, 'Kochhar' , 100 from dual union all
select 108, 'Greenberg' , 101 from dual union all
select 109, 'Faviet' , 108 from dual union all
select 110, 'Chen' , 108 from dual union all
select 111, 'Sciarra' , 108 from dual union all
select 112, 'Urman' , 108 from dual union all
select 113, 'Popp' , 108 from dual union all
select 200, 'Whalen' , 101 from dual
)
-- actual query
select employee_id
, manager_id
, concat(lpad('-', 3*level, '-'), last_name) as last_name
from (
-- using distinct to get rid of duplicate parents
select distinct last_name
, employee_id
, manager_id
from t1
start with last_name like '%a%'
connect by employee_id = prior manager_id
) q
start with manager_id = 100
connect by prior employee_id = manager_id
结果:
EMPLOYEE_ID MANAGER_ID LAST_NAME
----------- ---------- --------------------
101 100 ---Kochhar
108 101 ------Greenberg
109 108 ---------Faviet
111 108 ---------Sciarra
112 108 ---------Urman
200 101 ------Whalen
6 rows selected.