您的当前位置:首页正文

Oracle树查询及相关函数

2020-11-09 来源:品趣旅游知识分享网

欢迎进入Oracle社区论坛,与200万技术人员互动交流 >>进入 8.查询一个节点的父节点的的兄弟节点(伯父与叔父)。 Sql代码 WITH tmp AS (SELECT flfl.*, LEVEL lev FROM flfl START WITH sjflid IS NULL CONNECT BY sjflid = PRIOR ID) SELECT b.* FROM tmp b

欢迎进入Oracle社区论坛,与200万技术人员互动交流 >>进入

  8.查询一个节点的父节点的的兄弟节点(伯父与叔父)。

  Sql代码

  WITH tmp AS

  (SELECT flfl.*, LEVEL lev

  FROM flfl

  START WITH sjflid IS NULL

  CONNECT BY sjflid = PRIOR ID)

  SELECT b.*

  FROM tmp b,

  (SELECT *

  FROM tmp

  WHERE ID = 7004 AND lev = 2) a

  WHERE b.lev = 1

  UNION ALL

  SELECT *

  FROM tmp

  WHERE sjflid = (SELECT DISTINCT x.ID

  FROM tmp x,

  tmp y,

  (SELECT *

  FROM tmp

  WHERE ID = 7004 AND lev > 2) z

  WHERE y.ID = z.sjflid AND x.ID = y.sjflid);

  这里查询分成以下几步。首先,将第7个一样,将全表都使用临时表加上级别;其次,根据级别来判断有几种类型,以上文中举的例子来说,有三种情况:(1)当前节点为顶级节点,即查询出来的lev值为1,那么它没有上级节点,不予考虑。(2)当前节点为2级节点,查询出来的lev值为2,那么就只要保证lev级别为1的就是其上级节点的兄弟节点。(3)其它情况就是3以及以上级别,那么就要选查询出来其上级的上级节点(祖父),再来判断祖父的下级节点都是属于该节点的上级节点的兄弟节点。 最后,就是使用UNION将查询出来的结果进行结合起来,形成结果集。

  9.查询一个节点的父节点的同级节点(族叔)。

  这个其实跟第7种情况是相同的。

  Sql代码

  WITH tmp AS

  (SELECT a.*, LEVEL lev

  FROM flfl a

  START WITH a.sjflid IS NULL

  CONNECT BY a.sjflid = PRIOR a.ID)

  SELECT *

  FROM tmp

  WHERE lev = (SELECT lev

  FROM tmp

  WHERE ID = 819394) - 1

  只需要做个级别判断就成了。

  基本上,常见的查询在里面了,不常见的也有部分了。其中,查询的内容都是节点的基本信息,都是数据表中的基本字段,但是在树查询中还有些特殊需求,是对查询数据进行了处理的,常见的包括列出树路径等。

  补充一个概念,对于数据库来说,根节点并不一定是在数据库中设计的顶级节点,对于数据库来说,根节点就是start with开始的地方。

  下面列出的是一些与树相关的特殊需求。

  10.名称要列出名称全部路径。

  这里常见的有两种情况,一种是是从顶级列出,直到当前节点的名称(或者其它属性);一种是从当前节点列出,直到顶级节点的名称(或其它属性)。举地址为例:国内的习惯是从省开始、到市、到县、到居委会的,而国外的习惯正好相反(老师说的,还没接过国外的邮件,谁能寄个瞅瞅 )。

  从顶部开始:

  Sql代码

  SELECT SYS_CONNECT_BY_PATH (mc, '/')

  FROM flfl

  WHERE ID = 6498

  START WITH sjflid IS NULL

  CONNECT BY sjflid = PRIOR ID;

  从当前节点开始:

  Sql代码

  SELECT SYS_CONNECT_BY_PATH (mc, '/')

  FROM flfl

  START WITH ID = 6498

  CONNECT BY PRIOR sjflid = ID;

  在这里我又不得不放个牢骚了。oracle只提供了一个sys_connect_by_path函数,却忘了字符串的连接的顺序。在上面的例子中,第一个SQL是从根节点开始遍历,而第二个SQL是直接找到当前节点,从效率上来说已经是千差万别,更关键的是第一个SQL只能选择一个节点,而第二个SQL却是遍历出了一颗树来。再次PS一下。

  sys_connect_by_path函数就是从start with开始的地方开始遍历,并记下其遍历到的节点,start with开始的地方被视为根节点,将遍历到的路径根据函数中的分隔符,组成一个新的字符串,这个功能还是很强大的。

  11.列出当前节点的根节点。

  在前面说过,根节点就是start with开始的地方。

  Sql代码

  SELECT CONNECT_BY_ROOT mc, flfl.*

  FROM flfl

  START WITH ID = 6498

  CONNECT BY PRIOR sjflid = ID;

  connect_by_root函数用来列的前面,记录的是当前节点的根节点的内容。

  12.列出当前节点是否为叶子。

  这个比较常见,尤其在动态目录中,在查出的内容是否还有下级节点时,这个函数是很适用的。

  Sql代码

  SELECT CONNECT_BY_ISLEAF, flfl.*

  FROM flfl

  START WITH sjflid IS NULL

  CONNECT BY sjflid = PRIOR ID;

  connect_by_isleaf函数用来判断当前节点是否包含下级节点,如果包含的话,说明不是叶子节点,这里返回0;反之,如果不包含下级节点,这里返回1。

  至此,oracle树型查询基本上讲完了,以上的例子中的数据是使用到做过的项目中的数据,因为里面的内容可能不好理解,所以就全部用一些新的例子来进行阐述。以上所有SQL都在本机上测试通过,也都能实现相应的功能,但是并不能保证是解决这类问题的最优方案(如第8条明显写成存储过程会更好),如果谁有更好的解决方案、或者有关oracle树查询的任何问题,欢迎留言讨论,以上的SQL有什么问题也欢迎大家留言批评。

[1] [2]

显示全文