Mysql 如何在emp表中根据员工层次结构进行排名

Mysql 如何在emp表中根据员工层次结构进行排名,mysql,sql,oracle,Mysql,Sql,Oracle,我有emp表,金是公司的首席执行官,他没有经理。 国王应该获得“1”级。 金是琼斯、克拉克、布莱克的经理。因此,这些将获得排名“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

我有emp表,金是公司的首席执行官,他没有经理。 国王应该获得“1”级。 金是琼斯、克拉克、布莱克的经理。因此,这些将获得排名“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

提前谢谢。我希望这件事在甲骨文中完成。

过去我花了一段时间才对继承权的问题了如指掌。。。然而,一旦你花时间去摆弄它们,它们通常就没有那么难对付了

  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_数据只是为了伪造你的测试数据
  • 按管理器连接=先前的ename 这将获取每条记录,并将经理与上一级员工进行比较
  • “以mgr开头”为空 这告诉甲骨文从哪里开始
  • 等级是继承权的深度

我认为Oracle支持在
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):


在Oracle文档中搜索
connectby
子句和名为
LEVEL
的伪列。您列出了两种不同的RDBMS,这到底是用于哪个数据库,还是必须与数据库无关?SQL语法将因引擎而异。对于MySQL,没有办法。connect by是Oracle的专有扩展,也不支持recursice CTE(SQL标准)。使用用户变量和临时表,我相信在mySQL中可能有一种方法可以做到这一点。但不是在一条语句中。@xQbert我标记了msql以获取与引擎相关的特定命令以外的任何逻辑。正如我在问题中提到的,我更喜欢用甲骨文来回答。谢谢。今天我学习了新的子句连接方式,从开始。我想知道如果没有这个CONNECT BY子句,我们如何实现分层查询。我用您的输入得到了最终查询。查询是:
SELECT empno,ename,mgr,LEVEL FROM emp CONNECT BY previor empno=mgr START WITH mgr is null
使用递归公共表表达式也可以,但mySQL不支持它们。Oracle在较新版本中也有。@Naveen:我相信“递归子查询分解”也可以做到,但是,我仍然在努力解决这个问题以及O.O(基本上,它是一个自我引用的with子句…),谢谢你的回复。这是一个通用的,我使用CONNECT BY子句得到了答案。
ORDER BY decode(mgr, 'NULL', 1, 'KING', 2, ...)