![](/img/trans.png)
[英]SQL hierarchical query: find full tree given an id of any parent-child (Oracle)
[英]Given any child in the hierarchy, fetch complete tree by INFORMIX hierarchical SQL
我需要一些有关 Informix 分层 sql 查询的帮助。 我有以下结构的表:
create table empl_relation (
employee_id char(10),
manager_id char(10));
employee_id | manager_id
5148 null
5149 5148
5150 5149
5151 5148
5152 5151
5154 5148
5155 5154
我能够成功运行以下查询:
SELECT employee_id, manager_id FROM empl_relation
START WITH employee_id = 5148
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY employee_id;
它返回上表中指定的确切层次结构。 但是,我试图在这里实现一些不同的目标。 给定层次结构中的任何员工 ID 作为输入,我试图获得相同的结果集。 例如,在查询中,如果我指定5154作为输入employee_id,我应该能够获取输入employee id的所有父母和他们的孩子以及孩子和孙辈。 准确地说,我想要与通过运行上述查询获得的完全相同的结果集。
是否可以在单个查询中实现? 如果是的话,你能帮我实现这个目标吗?
EDIT
好的,我想出了一种方法来实现这一点,但它涉及执行 2 个查询,如下所示:
SELECT employee_id, manager_id FROM empl_relation
START WITH employee_id = 5150
CONNECT BY employee_id = PRIOR manager_id
ORDER SIBLINGS BY employee_id ;
这将返回:
employee_id | manager_id
5148
5149 5148
5150 5149
然后我们可以通过遍历结果集并执行以下查询来获取应用程序层上的父employee_id 以获取完整的层次树:
SELECT employee_id, manager_id FROM empl_relation
START WITH employee_id = 5148
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY employee_id;
这将工作正常,但如果我可以在单个查询中实现这一点,那就太好了。
这将您的两个查询合并为一个,并且似乎可以正常工作:
SELECT employee_id, manager_id FROM empl_relation
START WITH employee_id = (
SELECT h.employee_id
FROM (SELECT employee_id, manager_id
FROM empl_relation
START WITH employee_id = 5150
CONNECT BY employee_id = PRIOR manager_id
) AS h
WHERE h.manager_id IS NULL)
CONNECT BY PRIOR employee_id = manager_id
ORDER BY employee_id;
基本上,这将使用查询来构建层次结构并运行该查询,然后过滤结果以获取最高经理(没有经理的雇员),并将该值用作“从最高层次返回”查询中的START。
5148
5149 5148
5150 5149
5151 5148
5152 5151
5154 5148
5155 5154
我得到的任何初始值都相同:5148、5149、5150、5151、5152、5154、5155。
受到乔纳森(Jonathan)的答复的启发,我提出了他的查询的简短版本,如下所示
SELECT employee_id,manager_id FROM empl_relation
START WITH employee_id =
(SELECT employee_id
FROM empl_relation er
WHERE er.manager_id IS NULL
START WITH employee_id = 5150 CONNECT BY employee_id =
PRIOR manager_id)
CONNECT BY
PRIOR employee_id = manager_id
ORDER BY employee_id;
这似乎也很好。
在informix 12 及更高版本中,您可以在临时表的帮助下使用简单的合并语句,而不是使用分层查询来实现所需的结果。
使用以下 stmt 创建临时表:
select a.employee_id,
a.manager_id,
rpad(a.manager_id, 100, ' ') as manager_hier,
a.manager_id as topmanager
from empl_relation a
left join empl_relation b on a.manager_id = b.employee_id into temp emp_mgr_rel;
运行下面的合并 stmt 次数与树的最长分支的深度一样多。 多运行它不会影响最终结果,所以不用担心:
merge into emp_mgr_rel as a using emp_mgr_rel as b on a.topmanager = b.employee_id WHEN MATCHED THEN
UPDATE
set a.manager_hier = nvl(trim(a.manager_hier), '') || '-' || nvl(trim(b.topmanager), ''),
a.topmanager = trim(b.manager_hier);
使用以下 stmt 检查您的结果。 您将在manager_hier
列下看到层次结构为带连字符的值:
select employee_id, manager_hier from emp_mgr_rel;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.