Oracle按优先级分层排序连接

gzjq41n4  于 2023-11-17  发布在  Oracle
关注(0)|答案(3)|浏览(100)

我有一个表,其中定义了父/子关系,但没有办法通过层次结构进行排序。

For example consider this:
   empid  managerid   name 
    js       hd      George
    hd       ab       Mary
    hs       js       Tom
    ab       xx       John

字符串
既然我不能使用ORDER SIBLINGS BY进行分层排序,那么我如何能够像下面这样以分层方式进行排序呢?

empid managerid  name 
     ab       xx       John
     hd       ab       Mary
     js       hd      George
     hs       js       Tom

wbrvyc0a

wbrvyc0a1#

这将是有帮助的,以显示我们的查询,你已经尝试到目前为止。这听起来像是有一个误解的地方。
对于非常小的样本数据,Eng. Samer T的答案是正确的。您不需要order by子句。Oracle保证在connect by查询中按层次顺序返回行。Oracle documentation on Hierarchical Queries

  1. Oracle按图9-1所示的顺序返回行。在图中,* 子行出现在其父行的下面 *。
  • 不能 * 保证的是同一层次结构级别(兄弟)内的行将如何排序。但是因为样本数据在每个级别上只有一个子级,所以这实际上并不重要。

然而,让我们考虑一个有更多数据的例子,这样我们就有了兄弟姐妹。

create table Employee (
  empid varchar2(50) not null,
  managerid varchar2(50) not null,
  name varchar2(50) not null
)
/

insert into Employee (empid, managerid, name) values ('js', 'hd', 'George');
insert into Employee (empid, managerid, name) values ('hd', 'ab', 'Mary');
insert into Employee (empid, managerid, name) values ('hs', 'js', 'Tom');
insert into Employee (empid, managerid, name) values ('ww', 'js', 'Waldo');
insert into Employee (empid, managerid, name) values ('ab', 'xx', 'John');
insert into Employee (empid, managerid, name) values ('ab2', 'xx', 'Other manager');
insert into Employee (empid, managerid, name) values ('st', 'ab2', 'Stan');
insert into Employee (empid, managerid, name) values ('lee', 'ab2', 'Lee');

alter table employee
add constraint employee_pk
primary key (empid)
/

字符串
如果我运行下面的connect by查询 * 而不带order by子句:

select t.*, level
from employee t
start with t.managerid = 'xx'
connect by prior t.empid = t.managerid


我得到(SqlFiddle):

empid   managerid   name          level
-----   ---------   ----          -----
ab      xx          John            1
hd      ab          Mary            2
js      hd          George          3
hs      js          Tom             4
ww      js          Waldo           4
ab2     xx          Other manager   1
lee     ab2         Lee             2
st      ab2         Stan            2


注意层次结构是如何被尊重的,这是有保证的。然而,对于兄弟姐妹,顺序是不保证的。例如,不能保证John将 * 总是 * 在Other manager之前列出,Tom将在Waldo之前列出,或者Lee将在Stan之前列出。
如果您想保证兄弟中的顺序,但又不破坏层次结构的顺序,这正是order siblings by子句的作用。
所以我不知道你为什么说:
我不能使用ORDER SIBLINGS BY进行分层排序
因为,Oracle documentation on Hierarchical Queries几乎是相反的:
在分层查询中,不要指定ORDER BYGROUP BY,因为它们将覆盖CONNECT BY结果的分层顺序。如果要对同一父代的兄弟行进行排序,请使用ORDER SIBLINGS BY子句。
请注意它是如何特别推荐使用order siblings by来对兄弟进行排序的,而不会破坏结果的层次顺序。
假设我希望我的结果按层次结构排序,但兄弟节点按名称降序排序。然后我可以调整我之前的查询:

select t.*, level
from employee t
start with t.managerid = 'xx'
connect by prior t.empid = t.managerid
order siblings by name desc


我的结果变成了(SqlFiddle):

empid   managerid   name          level
-----   ---------   ----          -----
ab2     xx          Other manager   1
st      ab2         Stan            2
lee     ab2         Lee             2
ab      xx          John            1
hd      ab          Mary            2
js      hd          George          3
ww      js          Waldo           4
hs      js          Tom             4


请注意,层次结构仍然有效,但兄弟JohnOther manager被重新排序,因此Other manager的整个结果树都列在John之前。此外,Waldo现在总是出现在Tom之前,Stan总是出现在Lee之前。

qybjjes1

qybjjes12#

默认的“connect by”子句将返回结果。
从头开始,我假设“xx”意味着没有经理。

select t.*, t.rowid from emp_table t
start with managerid = 'xx'
connect by prior empid = managerid

字符串

相关问题