如何根据emp表中的员工层次结构给出RANK

时间:2015-05-11 20:12:54

标签: mysql sql oracle

我有emp table,KING是公司的CEO,他没有经理。 KING应该得到RANK'1'。 KING是JONES,CLARK,BLAKE的经理。所以这些将获得RANK'2'......等等。

emp和经理关系的中间表:

empno   ename   mgr
7566    JONES   KING
7782    CLARK   KING
7698    BLAKE   KING
7900    JAMES   BLAKE
7844    TURNER  BLAKE
7654    MARTIN  BLAKE
7521    WARD    BLAKE
7499    ALLEN   BLAKE
7934    MILLER  CLARK
7902    FORD    JONES
7788    SCOTT   JONES
7876    ADAMS   SCOTT
7369    SMITH   FORD
7839    KING    NULL

最终输出应该是:

mgr   rank    
KING    1
JONES   2
CLARK   2
BLAKE   2
JAMES   3
TURNER  3
MARTIN  3
WARD    3
ALLEN   3
MILLER  3
SCOTT   3
FORD    3
ADAMS   4
SMITH   4

提前致谢。我希望这能在oracle中完成。

2 个答案:

答案 0 :(得分:2)

过去我花了很多时间围绕着层面的问题...但是,一旦你花时间来摆弄它们,它们通常都不会那么艰难。

  SQL> with w_data as (
    2           select 7566 empno, rtrim('JONES ') ename, rtrim('KING ') mgr from dual union all
    3           select 7782 empno, rtrim('CLARK ') ename, rtrim('KING ') mgr from dual union all
    4           select 7698 empno, rtrim('BLAKE ') ename, rtrim('KING ') mgr from dual union all
    5           select 7900 empno, rtrim('JAMES ') ename, rtrim('BLAKE') mgr from dual union all
    6           select 7844 empno, rtrim('TURNER') ename, rtrim('BLAKE') mgr from dual union all
    7           select 7654 empno, rtrim('MARTIN') ename, rtrim('BLAKE') mgr from dual union all
    8           select 7521 empno, rtrim('WARD  ') ename, rtrim('BLAKE') mgr from dual union all
    9           select 7499 empno, rtrim('ALLEN ') ename, rtrim('BLAKE') mgr from dual union all
   10           select 7934 empno, rtrim('MILLER') ename, rtrim('CLARK') mgr from dual union all
   11           select 7902 empno, rtrim('FORD  ') ename, rtrim('JONES') mgr from dual union all
   12           select 7788 empno, rtrim('SCOTT ') ename, rtrim('JONES') mgr from dual union all
   13           select 7876 empno, rtrim('ADAMS ') ename, rtrim('SCOTT') mgr from dual union all
   14           select 7369 empno, rtrim('SMITH ') ename, rtrim('FORD ') mgr from dual union all
   15           select 7839 empno, rtrim('KING  ') ename, NULL           mgr from dual
   16           )
   17  select empno, ename, mgr, level
   18    from w_data
   19   connect by mgr = PRIOR ename
   20   start with mgr IS NULL
  /
   21
       EMPNO ENAME  MGR        LEVEL
  ---------- ------ ----- ----------
        7839 KING                  1
        7698 BLAKE  KING           2
        7499 ALLEN  BLAKE          3
        7900 JAMES  BLAKE          3
        7654 MARTIN BLAKE          3
        7844 TURNER BLAKE          3
        7521 WARD   BLAKE          3
        7782 CLARK  KING           2
        7934 MILLER CLARK          3
        7566 JONES  KING           2
        7902 FORD   JONES          3

       EMPNO ENAME  MGR        LEVEL
  ---------- ------ ----- ----------
        7369 SMITH  FORD           4
        7788 SCOTT  JONES          3
        7876 ADAMS  SCOTT          4

  14 rows selected.

  SQL>
  • w_data只是伪造你的测试数据..
  • 通过mgr =先前ename连接 这会记录每条记录,并将mgr与之前的员工进行比较。
  • 以mgr开头为空 这告诉Oracle从哪里开始......
  • 等级是层次的深度。

答案 1 :(得分:-2)

我相信Oracle在CASE WHERE子句中支持ORDER BY。像这样:

SELECT [blah]
FROM [intermediate tbl]
ORDER BY
    CASE WHEN mgr IS NULL THEN 1
    CASE WHEN mgr = 'KING' THEN 2
    ... ELSE ... END

我相信在Oracle中有一个更短的方法(我的经验是使用SSMS):

ORDER BY decode(mgr, 'NULL', 1, 'KING', 2, ...)