再求层次结构的PL/SQL 查询语句,新要求

happyxiaowuge00gou 2013-12-12 10:22:42
参考前一个帖子:
http://bbs.csdn.net/topics/390665736

现有新的需求,又实现不了了~~~求大神帮忙

测试表创建语句:
CREATE TABLE TEST_QUERY
(
ID VARCHAR2(10),--ID
PID VARCHAR2(10),----父文件夹ID
NAME VARCHAR2(100),----文件夹名称
IS_FOLDER NUMBER(1)-- 1:文件夹,0:文件
)
INSERT INTO TEST_QUERY VALUES('0000','0','A',1);
INSERT INTO TEST_QUERY VALUES('0001','0000','A01',1);
INSERT INTO TEST_QUERY VALUES('0002','0000','A02',1);
INSERT INTO TEST_QUERY VALUES('0003','0000','A03',1);
INSERT INTO TEST_QUERY VALUES('0007','0003','A03-01',0);
INSERT INTO TEST_QUERY VALUES('0008','0003','A03-02',0);
INSERT INTO TEST_QUERY VALUES('0009','0003','A03-03',0);
INSERT INTO TEST_QUERY VALUES('0004','0000','A04',0);
INSERT INTO TEST_QUERY VALUES('0005','0000','A05',0);
INSERT INTO TEST_QUERY VALUES('0006','0000','A06',0);
INSERT INTO TEST_QUERY VALUES('0010','0006','A06-01',0);
INSERT INTO TEST_QUERY VALUES('0011','0006','A06-02',0);
INSERT INTO TEST_QUERY VALUES('0012','0006','A06-03',1);
INSERT INTO TEST_QUERY VALUES('0013','0012','A06-03-01',0);
INSERT INTO TEST_QUERY VALUES('0014','0012','A06-03-02',0);
INSERT INTO TEST_QUERY VALUES('0015','0012','A06-03-03',0);

现在的要求是:
如果目录的最底层没有文件,那么这些目录就不查询出来,
而最底层有文件的,就把他的层次结构包括最底层的目录查询出来

即一棵树上,没有树叶的树枝不查询出来,如果有树叶,那么就把树叶连同树枝一起查询出来~~
请大神们帮忙
...全文
148 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
happyxiaowuge00gou 2013-12-12
  • 打赏
  • 举报
回复
引用 5 楼 z_shousi 的回复:
我勒个去,楼主把我3#忽略了。
这个真没有,已经按照兄台的思路改过来了,反向从树叶开始,查找所有树叶涉及的树枝,然后过滤掉不在这些范围内的树枝,即剪掉了没有树叶的树枝,然后再分层~~~搞定 ,嘎嘎 脚本如下:

SELECT TEST_QUERY.*,LEVEL
FROM TEST_QUERY
WHERE ID NOT IN(
  SELECT ID 
  FROM TEST_QUERY
  WHERE IS_FOLDER=1
       AND ID NOT IN
        (
        SELECT DISTINCT PID 
        FROM TEST_QUERY
        WHERE 1=1
        START WITH IS_FOLDER=0
        CONNECT BY PRIOR PID=ID
        )
  )
START WITH PID='0'
CONNECT BY PRIOR ID=PID
  • 打赏
  • 举报
回复
我勒个去,楼主把我3#忽略了。
happyxiaowuge00gou 2013-12-12
  • 打赏
  • 举报
回复
引用 1 楼 shiyiwan 的回复:
SQL> SELECT TEST_QUERY.*,LEVEL, CONNECT_BY_ISLEAF
  2  FROM TEST_QUERY
  3  where (CASE CONNECT_BY_ISLEAF WHEN 1 THEN IS_FOLDER ELSE 0 END) = 0
  4  START WITH TEST_QUERY.PID = '0'
  5  CONNECT BY PRIOR TEST_QUERY.ID = TEST_QUERY.PID
  6  /
 
ID         PID        NAME                                                                             IS_FOLDER      LEVEL CONNECT_BY_ISLEAF
---------- ---------- -------------------------------------------------------------------------------- --------- ---------- -----------------
0000       0          A                                                                                        1          1                 0
0003       0000       A03                                                                                      1          2                 0
0007       0003       A03-01                                                                                   0          3                 1
0008       0003       A03-02                                                                                   0          3                 1
0009       0003       A03-03                                                                                   0          3                 1
0004       0000       A04                                                                                      0          2                 1
0005       0000       A05                                                                                      0          2                 1
0006       0000       A06                                                                                      0          2                 0
0010       0006       A06-01                                                                                   0          3                 1
0011       0006       A06-02                                                                                   0          3                 1
0012       0006       A06-03                                                                                   1          3                 0
0013       0012       A06-03-01                                                                                0          4                 1
0014       0012       A06-03-02                                                                                0          4                 1
0015       0012       A06-03-03                                                                                0          4                 1
 
14 rows selected
 
SQL> 
我用我自己的脚本 和 您的脚本都试过,然后都发现了问题,比如A目录下有B目录,B目录下又有C目录,C目录下又有D目录,但是A、B、C、D目录下都没有文件,用我们的脚本都会把A给查出来~~~~
  • 打赏
  • 举报
回复
引用 1 楼 shiyiwan 的回复:
SQL> SELECT TEST_QUERY.*,LEVEL, CONNECT_BY_ISLEAF
  2  FROM TEST_QUERY
  3  where (CASE CONNECT_BY_ISLEAF WHEN 1 THEN IS_FOLDER ELSE 0 END) = 0
  4  START WITH TEST_QUERY.PID = '0'
  5  CONNECT BY PRIOR TEST_QUERY.ID = TEST_QUERY.PID
  6  /
 
ID         PID        NAME                                                                             IS_FOLDER      LEVEL CONNECT_BY_ISLEAF
---------- ---------- -------------------------------------------------------------------------------- --------- ---------- -----------------
0000       0          A                                                                                        1          1                 0
0003       0000       A03                                                                                      1          2                 0
0007       0003       A03-01                                                                                   0          3                 1
0008       0003       A03-02                                                                                   0          3                 1
0009       0003       A03-03                                                                                   0          3                 1
0004       0000       A04                                                                                      0          2                 1
0005       0000       A05                                                                                      0          2                 1
0006       0000       A06                                                                                      0          2                 0
0010       0006       A06-01                                                                                   0          3                 1
0011       0006       A06-02                                                                                   0          3                 1
0012       0006       A06-03                                                                                   1          3                 0
0013       0012       A06-03-01                                                                                0          4                 1
0014       0012       A06-03-02                                                                                0          4                 1
0015       0012       A06-03-03                                                                                0          4                 1
 
14 rows selected
 
SQL> 
这个不能满足假如叶子不为文件,树枝不查询出的效果吧。 例如 0016 0000 A07 1 0017 0016 A07-01 1 以上sql会把0016查询出来。 我的思路是先查询出所有叶子节点为文件夹的id,反向查询父节点。

SELECT distinct id,pid,name,is_folder
FROM test_query 
START WITH id in (
select id from(
SELECT id,is_folder,
CONNECT_BY_ISLEAF "ISLEAF"
FROM test_query 
START WITH pid = '0'
CONNECT BY PRIOR id = pid ) t
where t.isleaf = 1 and t.is_folder=0
)
CONNECT BY PRIOR pid = id
order by id
happyxiaowuge00gou 2013-12-12
  • 打赏
  • 举报
回复
引用 1 楼 shiyiwan 的回复:
SQL> SELECT TEST_QUERY.*,LEVEL, CONNECT_BY_ISLEAF
  2  FROM TEST_QUERY
  3  where (CASE CONNECT_BY_ISLEAF WHEN 1 THEN IS_FOLDER ELSE 0 END) = 0
  4  START WITH TEST_QUERY.PID = '0'
  5  CONNECT BY PRIOR TEST_QUERY.ID = TEST_QUERY.PID
  6  /
 
ID         PID        NAME                                                                             IS_FOLDER      LEVEL CONNECT_BY_ISLEAF
---------- ---------- -------------------------------------------------------------------------------- --------- ---------- -----------------
0000       0          A                                                                                        1          1                 0
0003       0000       A03                                                                                      1          2                 0
0007       0003       A03-01                                                                                   0          3                 1
0008       0003       A03-02                                                                                   0          3                 1
0009       0003       A03-03                                                                                   0          3                 1
0004       0000       A04                                                                                      0          2                 1
0005       0000       A05                                                                                      0          2                 1
0006       0000       A06                                                                                      0          2                 0
0010       0006       A06-01                                                                                   0          3                 1
0011       0006       A06-02                                                                                   0          3                 1
0012       0006       A06-03                                                                                   1          3                 0
0013       0012       A06-03-01                                                                                0          4                 1
0014       0012       A06-03-02                                                                                0          4                 1
0015       0012       A06-03-03                                                                                0          4                 1
 
14 rows selected
 
SQL> 
感谢大神,我也写了一个语句实现了,不过没有大神的简介,供参考

select test_query.*,LEVEL
from test_query 
where id not in
(
     SELECT ID 
     FROM   Test_Query 
     WHERE  is_folder=1 
           and id not in(select distinct pid from test_query)
)
START WITH PID='0'
connect by prior id=pid
shiyiwan 2013-12-12
  • 打赏
  • 举报
回复
SQL> SELECT TEST_QUERY.*,LEVEL, CONNECT_BY_ISLEAF
  2  FROM TEST_QUERY
  3  where (CASE CONNECT_BY_ISLEAF WHEN 1 THEN IS_FOLDER ELSE 0 END) = 0
  4  START WITH TEST_QUERY.PID = '0'
  5  CONNECT BY PRIOR TEST_QUERY.ID = TEST_QUERY.PID
  6  /
 
ID         PID        NAME                                                                             IS_FOLDER      LEVEL CONNECT_BY_ISLEAF
---------- ---------- -------------------------------------------------------------------------------- --------- ---------- -----------------
0000       0          A                                                                                        1          1                 0
0003       0000       A03                                                                                      1          2                 0
0007       0003       A03-01                                                                                   0          3                 1
0008       0003       A03-02                                                                                   0          3                 1
0009       0003       A03-03                                                                                   0          3                 1
0004       0000       A04                                                                                      0          2                 1
0005       0000       A05                                                                                      0          2                 1
0006       0000       A06                                                                                      0          2                 0
0010       0006       A06-01                                                                                   0          3                 1
0011       0006       A06-02                                                                                   0          3                 1
0012       0006       A06-03                                                                                   1          3                 0
0013       0012       A06-03-01                                                                                0          4                 1
0014       0012       A06-03-02                                                                                0          4                 1
0015       0012       A06-03-03                                                                                0          4                 1
 
14 rows selected
 
SQL> 
Leon_He2014 2013-12-12
  • 打赏
  • 举报
回复

SELECT test_query.*
,LEVEL
FROM test_query
WHERE ID IN (
SELECT PID
FROM test_query
START WITH is_folder=0
CONNECT BY PRIOR ID=pid 
UNION 
SELECT ID
FROM  test_query
WHERE is_folder=0
)
START WITH pid='0'
CONNECT BY PRIOR ID= pid;
我也写个
shiyiwan 2013-12-12
  • 打赏
  • 举报
回复
引用 6 楼 happyxiaowuge00gou 的回复:
这个真没有,已经按照兄台的思路改过来了,反向从树叶开始,查找所有树叶涉及的树枝,然后过滤掉不在这些范围内的树枝,即剪掉了没有树叶的树枝,然后再分层~~~搞定 ,嘎嘎 脚本如下:

SELECT TEST_QUERY.*,LEVEL
FROM TEST_QUERY
WHERE ID NOT IN(
  SELECT ID 
  FROM TEST_QUERY
  WHERE IS_FOLDER=1
       AND ID NOT IN
        (
        SELECT DISTINCT PID 
        FROM TEST_QUERY
        WHERE 1=1
        START WITH IS_FOLDER=0
        CONNECT BY PRIOR PID=ID
        )
  )
START WITH PID='0'
CONNECT BY PRIOR ID=PID
引用 5 楼 z_shousi 的回复:
我勒个去,楼主把我3#忽略了。
都不错,z_shousi是根据符合条件的树叶反向查,happyxiaowuge00gou是剔除不符合条件之后查全部。可谓殊途同归
shiyiwan 2013-12-12
  • 打赏
  • 举报
回复
引用 3 楼 z_shousi 的回复:
这个不能满足假如叶子不为文件,树枝不查询出的效果吧。 例如 0016 0000 A07 1 0017 0016 A07-01 1 以上sql会把0016查询出来。 我的思路是先查询出所有叶子节点为文件夹的id,反向查询父节点。

SELECT distinct id,pid,name,is_folder
FROM test_query 
START WITH id in (
select id from(
SELECT id,is_folder,
CONNECT_BY_ISLEAF "ISLEAF"
FROM test_query 
START WITH pid = '0'
CONNECT BY PRIOR id = pid ) t
where t.isleaf = 1 and t.is_folder=0
)
CONNECT BY PRIOR pid = id
order by id
确实是的,欠考虑只过滤了树叶没有过滤树枝。
编辑推荐 近15年来,成千上万的PL/SQL程序员──无论是初学者还是经验丰富的开发者──都同样需要依赖《Oracle PL/SQL程序设计》来帮助他们充分掌握和应用这门功能强大的语言。 第5版是基于Oracle数据库11g的R1、R2两个版本的最版,包含了语法、建议、大量实例和许多的信息。 ?了解特征,包括基于版本的重定义功能、函数结果缓存功能、CONTINUE语句、复合触发器和针对大对象的SecureFiles。 ? 使用工具和技巧来优化PL/SQL性能,例如PL/Scope和PL/SQL中的层次化profiler。 ? 探讨了数据类型、条件控制语句和顺序控制语句、循环、异常处理、安全特性、全球化和本地化问题, 以及PL/SQL架构。 ? 通过使用过程、函数、触发器和包,建立模块化的PL/SQL应用。 内容推荐 《Oracle PL/SQL程序设计(第5版)》基于Oracle数据库11g,从PL/SQL编程、PL/SQL程序结构、PL/SQL程序数据、PL/SQL中的SQLPL/SQL应用构建、高级PL/SQL主题这6个方面详细系统地讨论了PL/SQL以及如何有效地使用它。本书能够帮助你充分利用PL/SQL来解决数据库开发中遇到的各种问题,引导你掌握各种构建应用的技巧和技术,以便使你编写出高效、可维护的代码。《Oracle PL/SQL程序设计(第5版)》不但介绍了大量的Oracle 11g的PL/SQL性能,还提供了许多优化PL/SQL性能的方法。   《Oracle PL/SQL程序设计(第5版)》结构清晰,示例丰富,实践性强,适用于Oracle数据库开发人员、Oracle数据库管理员等相关数据库从业人员,也可以作为各大、中专院校相关专业师生的参考用书和相关培训机构的培训教材。 目录: 目 录(上册) 第1部分 PL/SQL编程 第1章 PL/SQL概述 3 第2章 创建并运行PL/SQL代码 21 第3章 语言基础 50 第2部分 PL/SQL程序结构 第4章 条件和顺序控制 77 第5章 用循环进行迭代处理 96 第6章 异常处理 118 第3部分 PL/SQL数据 第7章 使用数据 159 第8章 字符串 182 第9章 数字 221 第10章 日期和时间戳 255 第11章 记录类型 297 第12章 集合 313 第13章 其他数据类型 381 第4部分 PL/SQL中的SQL 第14章 DML和事务管理 423 第15章 数据提取 444 第16章 动态SQL和动态PL/SQL 492 目 录(下册) 第5部分 构造PL/SQL应用程序 第17章 过程、函数与参数 543 第18章 包 593 第19章 触发器 626 第20章 管理PL/SQL代码 685 第21章 PL/SQL的性能优化 753 第22章 I/O操作和PL/SQL 843 第6部分 高级PL/SQL主题 第23章 应用安全与PL/SQL 887 第24章 PL/SQL架构 947 第25章 PL/SQL的全球化和本地化 993 第26章 PL/SQL的面向对象特性 1034 附录A 正则表达式的元字符和函数参数 1093 A.1 元字符 1093 A.2 函数和参数 1096 A.2.1 正则表达式函数 1096 A.2.2 正则表达式参数 1097 附录B 数字格式模型 1099 附录C 日期格式模型 1102
近15年来,成千上万的PL/SQL程序员──无论是初学者还是经验丰富的开发者──都同样需要依赖《Oracle PL/SQL程序设计》来帮助他们充分掌握和应用这门功能强大的语言。 第5版是基于Oracle数据库11g的R1、R2两个版本的最版,包含了语法、建议、大量实例和许多的信息。 ?了解特征,包括基于版本的重定义功能、函数结果缓存功能、CONTINUE语句、复合触发器和针对大对象的SecureFiles。 ? 使用工具和技巧来优化PL/SQL性能,例如PL/Scope和PL/SQL中的层次化profiler。 ? 探讨了数据类型、条件控制语句和顺序控制语句、循环、异常处理、安全特性、全球化和本地化问题, 以及PL/SQL架构。 ? 通过使用过程、函数、触发器和包,建立模块化的PL/SQL应用。 内容推荐 《Oracle PL/SQL程序设计(第5版)》基于Oracle数据库11g,从PL/SQL编程、PL/SQL程序结构、PL/SQL程序数据、PL/SQL中的SQLPL/SQL应用构建、高级PL/SQL主题这6个方面详细系统地讨论了PL/SQL以及如何有效地使用它。本书能够帮助你充分利用PL/SQL来解决数据库开发中遇到的各种问题,引导你掌握各种构建应用的技巧和技术,以便使你编写出高效、可维护的代码。《Oracle PL/SQL程序设计(第5版)》不但介绍了大量的Oracle 11g的PL/SQL性能,还提供了许多优化PL/SQL性能的方法。   《Oracle PL/SQL程序设计(第5版)》结构清晰,示例丰富,实践性强,适用于Oracle数据库开发人员、Oracle数据库管理员等相关数据库从业人员,也可以作为各大、中专院校相关专业师生的参考用书和相关培训机构的培训教材。 目录: 目 录(上册) 第1部分 PL/SQL编程 第1章 PL/SQL概述 3 第2章 创建并运行PL/SQL代码 21 第3章 语言基础 50 第2部分 PL/SQL程序结构 第4章 条件和顺序控制 77 第5章 用循环进行迭代处理 96 第6章 异常处理 118 第3部分 PL/SQL数据 第7章 使用数据 159 第8章 字符串 182 第9章 数字 221 第10章 日期和时间戳 255 第11章 记录类型 297 第12章 集合 313 第13章 其他数据类型 381 第4部分 PL/SQL中的SQL 第14章 DML和事务管理 423 第15章 数据提取 444 第16章 动态SQL和动态PL/SQL 492 目 录(下册) 第5部分 构造PL/SQL应用程序 第17章 过程、函数与参数 543 第18章 包 593 第19章 触发器 626 第20章 管理PL/SQL代码 685 第21章 PL/SQL的性能优化 753 第22章 I/O操作和PL/SQL 843 第6部分 高级PL/SQL主题 第23章 应用安全与PL/SQL 887 第24章 PL/SQL架构 947 第25章 PL/SQL的全球化和本地化 993 第26章 PL/SQL的面向对象特性 1034 附录A 正则表达式的元字符和函数参数 1093 A.1 元字符 1093 A.2 函数和参数 1096 A.2.1 正则表达式函数 1096 A.2.2 正则表达式参数 1097 附录B 数字格式模型 1099 附录C 日期格式模型 1102

17,382

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 基础和管理
社区管理员
  • 基础和管理社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧