给定任何节点作为输入的Oracle SQL完整层次结构
我想在Oracle SQL数据库中创建一个完整的层次搜索查询。 我有一个下表,叫做“项目” 输入是id列中给定id的任意一个。它应该能找到这个身份证的所有孩子,他们的孩子。还有父母和他们的父母。 目前我有以下疑问:给定任何节点作为输入的Oracle SQL完整层次结构,sql,oracle,hierarchical-data,Sql,Oracle,Hierarchical Data,我想在Oracle SQL数据库中创建一个完整的层次搜索查询。 我有一个下表,叫做“项目” 输入是id列中给定id的任意一个。它应该能找到这个身份证的所有孩子,他们的孩子。还有父母和他们的父母。 目前我有以下疑问: select distinct m.id, m.parent_id from item m connect by prior m.id = m.parent_id start with m.parent_id IN ( select m.parent_
select distinct m.id, m.parent_id
from item m
connect by prior m.id = m.parent_id
start with m.parent_id IN (
select m.parent_id
from item m
connect by m.id = prior m.parent_id
start with m.id = 3
union
select m.parent_id
from item m
where m.parent_id = 3);
目前,它似乎只是为了不选择没有父项(parent_id列为null)的父项而工作。除此之外,它似乎正在发挥作用。如果我的问题可以简化,我也会很感激的
编辑
我想我通过以下查询得到了期望的结果:
select m.id
from item m
start with m.id in (
select m.id
from item m
where connect_by_isleaf = 1
start with m.id = 3
connect by m.id = prior m.parent_id
)
connect by m.parent_id = prior m.id;
现在我有下一个问题。从m.id=3开始。问题是我想从整个查询中创建一个视图。但由于m.id值在不同的查询中发生变化,我无法将其添加为参数。还可以注释掉以m.id=3开头的内容,然后返回所有项之间的所有层次结构。有没有办法创建一些连接?例如:我将查询所有项目的所有这些关系,然后根据某些条件仅获取某些项目关系。如果要将其用作视图,可以执行以下操作:
WITH rek AS (SELECT item.id
, item.name
, connect_by_root item.id root_id
FROM item
START WITH parent_id IS null
CONNECT BY NOCYCLE parent_id = PRIOR id)
SELECT startItem.id startId
, startItem.name startName
, childItem.id childID
, childItem.name childName
FROM rek startItem
JOIN rek childItem
USING (root_id)
-- WHERE startItem.id = 3 -- This would be done from outside the view
子查询rek
将树的所有同级元素与根元素连接起来。然后,您只需使用此查询两次并通过根元素连接它,即可获得通过父子关系连接的所有元素
如果要减少结果集,可以使用SYS\u CONNECT\u BY\u PATH
来减少结果集:
WITH rek AS (SELECT item.id
, item.name
, connect_by_root item.id root_id
, SYS_CONNECT_BY_PATH(item.id, '/') path
FROM item
START WITH parent_id IS null
CONNECT BY NOCYCLE parent_id = PRIOR id)
SELECT startItem.id startId
, startItem.name startName
, childItem.id childID
, childItem.name childName
, childItem.path
FROM rek startItem
JOIN rek childItem
ON startItem.root_id = childItem.root_id
AND (startItem.path LIKE childItem.path||'/%'
OR childItem.path LIKE startItem.path||'/%'
OR childItem.id = startItem.id)
例如,这将只为您的孩子和家长提供起点,而不提供来自其他Leaf的条目。Oracle设置:
CREATE TABLE item ( id, name, parent_id ) AS
SELECT 1, 'A', NULL FROM DUAL UNION ALL
SELECT 2, 'B', 1 FROM DUAL UNION ALL
SELECT 3, 'C', 2 FROM DUAL UNION ALL
SELECT 4, 'D', 3 FROM DUAL UNION ALL
SELECT 5, 'E', 2 FROM DUAL;
ID NAME PARENT_ID
-- ---- ---------
1 A -
2 B 1
3 C 2
4 D 3
5 E 2
您可以使用以下方式获取项目及其所有祖先:
SELECT *
FROM item
START WITH id = 2
CONNECT BY PRIOR parent_id = id
您可以使用以下方法获取项目的所有子体:
SELECT *
FROM item
START WITH parent_id = 2
CONNECT BY PRIOR id = parent_id
您可以使用UNION ALL
将两者结合起来。然而,这将匹配项按增加祖先的顺序排列在祖先之前,然后按减少祖先的顺序排列在后代之后。。。这可能会让人困惑
因此,您可以对查询进行重新排序,以使两者的顺序一致:
SELECT *
FROM (
SELECT *
FROM item
START WITH id = 2
CONNECT BY PRIOR parent_id = id
ORDER BY LEVEL DESC
)
UNION ALL
SELECT *
FROM (
SELECT *
FROM item
START WITH parent_id = 2
CONNECT BY PRIOR id = parent_id
ORDER SIBLINGS BY name
);
输出:
CREATE TABLE item ( id, name, parent_id ) AS
SELECT 1, 'A', NULL FROM DUAL UNION ALL
SELECT 2, 'B', 1 FROM DUAL UNION ALL
SELECT 3, 'C', 2 FROM DUAL UNION ALL
SELECT 4, 'D', 3 FROM DUAL UNION ALL
SELECT 5, 'E', 2 FROM DUAL;
ID NAME PARENT_ID
-- ---- ---------
1 A -
2 B 1
3 C 2
4 D 3
5 E 2
“如果我的给定查询可以简化”问题是,虽然查询项的后代很简单,查询项的祖先也很简单,但在同一个查询中同时执行这两个操作是很棘手的。预期的输出格式是什么?预期的输出是所有父项和所有子项。从我的示例数据来看,所有这些节点都是通过父节点和子节点连接的,直到没有父节点的根节点。因此,所有这些都应该被选中。您的查询是错误的,因为当起始
id
为3
(或4
)时,输出包含5
,但5
不是3
(或4
)的祖先或后代-它位于层次结构的单独分支中。抱歉,如果我的描述不清楚的话。当起始id为3时。那么它的父级是2。2是3和5的父级。整个想法是我从表中随机抽取id。然后把这个id给所有的孩子和他们的孩子。还有所有的父母和那些父母的孩子。谢谢!结果按预期工作,类似于我在编辑零件后的初始问题后的查询。但是,有没有一种方法可以以某种方式使用此查询,使其成为视图,并且给定id=2和parent_id=2不在查询中。这意味着结果将用于例如:列,其中结果是用于那些id和父id的值。@j请不要使用带有动态输入值的视图,否。谢谢您的解决方案。它确实帮助我达到了预期的效果。