2011-04-21 72 views
0

下面是一个查询,它为员工返回主管链,但它使用了一堆嵌套的SELECT语句。 我想知道这个查询是否可以被重构为更有效率。该查询适用于3级管理授权员工参加培训课程的应用程序。目前我们需要3个级别的批准,但是这可能会更改为4个或更多。优化Oracle SQL查询

SELECT badge as employee, 
    supervisor_badge as boss1, 
    (select supervisor_badge FROM hr_data level2 WHERE badge = level1.supervisor_badge) as boss2 
    (select supervisor_badge FROM hr_data level3 WHERE badge = 
      (select supervisor_badge FROM hr_data level2 WHERE badge = level1.supervisor_badge)) as boss3 
    FROM hr_data level1 WHERE BADGE = '123456'; 

徽章=雇员的ID
supervisor_badge =
博特字段是hr_data表员工的主管的徽章

  badge supervisor_badge 
      123456 111111 
      111111 454545 
      454545 332211 

输出

employee  boss1  boss2  boss3 
123456   111111  454545  332211 
+0

你想让它运行得更快吗?还是希望它更加动态?所以你的关卡可以增长而不需要改变select语句? – Niklas 2011-04-21 17:27:03

+0

我觉得很容易维护。申请专家可能会要求我有5个级别的批准。下面的Mikes答案可以很容易地做到这一点。 – jeff 2011-04-21 18:36:52

回答

1

我没有一个方便的数据库来模拟这个,所以我将它。为了清晰起见,我尝试使用相同的命名约定。

SELECT level1.badge as employee 
     ,level2.badge as boss1 
     ,level3.badge as boss2 
     ,level3.supervisor_badge as boss3 
FROM hr_data level1 
     INNER JOIN hr_data level2 
      ON level2.badge = level1.supervisor_badge 
     INNER JOIN hr_data level3 
      ON level3.badge = level2.supervisor_badge 
WHERE  level1.badge = '123456' 

重要提示:其中存在的数据,在所有联接这只会返回记录。要返回少于3个老板的记录(即只有boss1和boss2,但没有老板3),请将INNER JOIN报表更改为LEFT JOIN

+0

谢谢迈克。您的查询正确无误地正常工作。它可以轻松添加或删除关卡。 – jeff 2011-04-21 18:35:48

1

使用联接,而不是子查询。

SELECT 
    e.badge, b1.badge, b2.badge, b3.badge 
FROM 
    hr_data e 
LEFT JOIN hr_data b1 ON e.badge=b1.badge 
LEFT JOIN hr_data b2 ON b1.badge=b2.badge 
LEFT JOIN hr_data b3 ON b2.badge=b3.badge 
WHERE 
    e.badge='123456'; 

随着级别是可变的,你可能要考虑使用一个存储过程来为内部水平的预先设定数量的循环(直到达到顶部,例如,你的CEO)。

+0

+1提醒我关于使用JOINS而不是SUBQUERIES。但是,您的查询缺少主管徽章。 – jeff 2011-04-21 18:32:48