我们有一个包含自引用树结构的表(id
,parent_id
)。让我们假设以下树结构:
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
我想获取此数据以便在树中显示它。但只有某些记录扩大了。我目前正在使用以下查询:
SELECT ID, NAME "PATH"
FROM GROUPS
WHERE PRIOR ID IN(1, 4)
CONNECT BY PARENT_ID = PRIOR ID
START WITH PARENT_ID IS NULL;
这非常有效,并返回以下记录:
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
问题是此查询返回扩展直接父级的所有记录,但不返回整个父链。因此,如果我们只是在扩展ID 4
,则不应该返回记录5, 6, 7
,因为1
未展开。
到目前为止,我一直在尝试获取一个自定义列,该列指示元素是否已展开,该列计算是否显式扩展并且父元素也已展开。
SELECT ...
CASE WHEN (ID IN (4) AND PRIOR EXPANDED = 1) THEN 1 ELSE 0 end "EXPANDED"
...
WHERE "EXPANDED" = 1
这不起作用,因为我在WHERE语句和EXPANDED
语句中都不能使用PRIOR EXPANDED
别名。
是否有一种使用简单查询实现此目的的简单方法?
答案 0 :(得分:3)
Oracle安装程序:
CREATE TABLE hierarchy ( id, parent_id ) AS
SELECT 1, NULL FROM DUAL UNION ALL
SELECT 2, 1 FROM DUAL UNION ALL
SELECT 3, 2 FROM DUAL UNION ALL
SELECT 4, 1 FROM DUAL UNION ALL
SELECT 5, 4 FROM DUAL UNION ALL
SELECT 6, 5 FROM DUAL UNION ALL
SELECT 7, NULL FROM DUAL UNION ALL
SELECT 8, 7 FROM DUAL UNION ALL
SELECT 9, 8 FROM DUAL UNION ALL
SELECT 10, 9 FROM DUAL UNION ALL
SELECT 11, 8 FROM DUAL;
查询 - IN
子句让所有父母都解释:
SELECT LPAD( '+ ', LEVEL*2, ' ' ) || id
FROM hierarchy
START WITH parent_id IS NULL
CONNECT BY PRIOR id = parent_id
AND parent_id IN ( 1, 2, 4, 5, 7, 8, 9 );
<强>输出强>:
+ 1
+ 2
+ 3
+4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
查询 - IN
子句扩展了所有父级,除了4和8 :
SELECT LPAD( '+ ', LEVEL*2, ' ' ) || id
FROM hierarchy
START WITH parent_id IS NULL
CONNECT BY PRIOR id = parent_id
AND parent_id IN ( 1, 2, 5, 7, 9 );
<强>输出强>:
+ 1
+ 2
+ 3
+4
+ 7
+ 8
更新 - 显示叶节点:
SELECT LPAD( '+ ', LEVEL*2, ' ' ) || id AS value,
isleaf
FROM (
-- Find the leaves first (as if all parents are expanded)
SELECT h.*,
CONNECT_BY_ISLEAF AS isLeaf
FROM hierarchy h
START WITH parent_id IS NULL
CONNECT BY PRIOR id = parent_id
)
START WITH parent_id IS NULL
CONNECT BY PRIOR id = parent_id
AND parent_id IN ( 1, 2, 4, 7, 9 );
<强>输出强>:
VALUE ISLEAF
---------------- ----------
+ 1 0
+ 2 0
+ 3 1
+ 4 0
+ 5 0
+ 7 0
+ 8 0
1
表示该节点没有子节点,0
表示该节点有子节点(即使它们可能未展开)。
答案 1 :(得分:0)
好的,只是看到了关于要求扩展整个父链的说明。以下是通过使用sys_connect_by_path构建该链,然后检查它是否为1(必须丢弃当前级别的最后一个节点)来完成此操作:
随着1和4的扩展,你得到:
WITH hier as (
SELECT 1 id, NULL parent_id, 1 expanded FROM DUAL UNION ALL
SELECT 2, 1, 0 FROM DUAL UNION ALL
SELECT 3, 2, 0 FROM DUAL UNION ALL
SELECT 4, 1, 1 FROM DUAL UNION ALL
SELECT 5, 4, 0 FROM DUAL UNION ALL
SELECT 6, 4, 0 FROM DUAL UNION ALL
SELECT 7, 4, 0 FROM DUAL UNION ALL
SELECT 8, 1, 0 FROM DUAL UNION ALL
SELECT 9, 1, 0 FROM DUAL UNION ALL
SELECT 10, 9, 0 FROM DUAL UNION ALL
SELECT 11, 9, 0 FROM DUAL )
SELECT LPAD( '+ ', lvl*2, ' ' ) || id
FROM (
SELECT ID
, parent_id
, level as lvl
, sys_connect_by_path(expanded,'-') as path_expanded
FROM hier
CONNECT BY PARENT_ID = PRIOR ID
START WITH PARENT_ID IS NULL
)
WHERE --every node in the path from the parent is expanded.
instr(substr(path_expanded,1,length(path_expanded)-2),'0') = 0
OR parent_id is null ;
LPAD('+',LVL*2,'')||ID
+ 1
+ 2
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
更改为在节点1取消展开,您将获得:
WITH hier as (
SELECT 1 id, NULL parent_id, 0 expanded FROM DUAL UNION ALL
SELECT 2, 1, 0 FROM DUAL UNION ALL
SELECT 3, 2, 0 FROM DUAL UNION ALL
SELECT 4, 1, 1 FROM DUAL UNION ALL
SELECT 5, 4, 0 FROM DUAL UNION ALL
SELECT 6, 4, 0 FROM DUAL UNION ALL
SELECT 7, 4, 0 FROM DUAL UNION ALL
SELECT 8, 1, 0 FROM DUAL UNION ALL
SELECT 9, 1, 0 FROM DUAL UNION ALL
SELECT 10, 9, 0 FROM DUAL UNION ALL
SELECT 11, 9, 0 FROM DUAL )
SELECT LPAD( '+ ', lvl*2, ' ' ) || id
FROM (
SELECT ID
, parent_id
, level as lvl
, sys_connect_by_path(expanded,'-') as path_expanded
FROM hier
CONNECT BY PARENT_ID = PRIOR ID
START WITH PARENT_ID IS NULL
)
WHERE --every node in the path from the parent is expanded.
instr(substr(path_expanded,1,length(path_expanded)-2),'0') = 0
OR parent_id is null ;
LPAD('+',LVL*2,'')||ID
+ 1