【问题标题】:Recursive hierarchical Oracle SQL query递归分层 Oracle SQL 查询
【发布时间】:2017-06-08 03:08:19
【问题描述】:

我有一个如下的源表:

Emp_ID| Name| Manager_ID
001|abc|005
005|cde|010
010|xyz|050
050 | bcg| 100
100|sta|NULL

我的要求是填充目标表,如下所示:

Emp_ID| Name| Manager_1| Manager_2| Manager_3| Manager_4
005|cde|xyz|bcg|sta|NULL
050|bcg|sta| NULL|NULL|NULL
100|sta|NULL|NULL|NULL
001|abc|cde|xyz|bcg|sta

我可以通过 Connect by 子句使用递归选择并填充 Manager_1 的值,但无法通过逻辑将 Manager_2、Manager_3、Manager_4 值填充为单行中的不同列值,具体取决于多少级别特定员工存在层次结构。 请帮忙。

【问题讨论】:

  • 这个要求是荒谬的。除非您知道“通过外部方式”(不查看数据),否则您甚至不知道输出需要扩展多远(多少列),并且在不提前知道列数的情况下,不可能编写SQL 查询。您将需要动态 SQL,这是不推荐的,通常是设计不佳的标志。 (这个查询的输出显然设计得很糟糕。)这是一项工作任务还是他们在课堂上教的东西?
  • 使用枢轴表达式。
  • 您当前的查询是什么,它会产生什么输出?
  • @mathguy:它的工作分配类型.. 我尝试使用 Oracle SQL 中提供的 'with select' 子句和路径选项
  • @access_granted:您能否详细说明一下“枢轴”选项。这会很有帮助。

标签: oracle recursion hierarchical-data


【解决方案1】:

我认为以下查询会对您有所帮助。但是要将字符串拆分为单个经理 ID,您需要知道经理级别的最大数量。

WITH data_set AS
     (SELECT '001' emp_id, 'aaa' emp_name, '005' mgr_id
        FROM DUAL
      UNION
      SELECT '005' emp_id, 'bbb' emp_name, '010' mgr_id
        FROM DUAL
      UNION
      SELECT '010' emp_id, 'ccc' emp_name, '050' mgr_id
        FROM DUAL
      UNION
      SELECT '020' emp_id, 'ddd' emp_name, '050' mgr_id
        FROM DUAL
      UNION
      SELECT '050' emp_id, 'eee' emp_name, '100' mgr_id
        FROM DUAL
      UNION
      SELECT '100' emp_id, 'fff' emp_name, '200' mgr_id
        FROM DUAL
      UNION
      SELECT '200' emp_id, 'ggg' emp_name, NULL mgr_id
        FROM DUAL)
SELECT     emp_id, emp_name, mgr_id,
           LTRIM (SYS_CONNECT_BY_PATH (emp_id, '-'), '-') chain
      FROM data_set
START WITH mgr_id IS NULL
CONNECT BY mgr_id = PRIOR emp_id
  ORDER SIBLINGS BY emp_id;

【讨论】:

  • 您能否发布最终查询,因为我很好奇您最终是如何处理它的。如果它解决了您的查询@suk15,也请标记可接受的答案
【解决方案2】:

如果您的层次结构仅延伸到 4 级深度,则可以使用以下查询:

select t1.Emp_ID, 
       t1.Name, 
       t2.Name as Manager_1, 
       t3.Name as Manager_2, 
       t4.Name as Manager_3,
       t5.Name as Manager_4
from tmp t1
left join tmp t2 on t2.Emp_ID = t1.Manager_ID
left join tmp t3 on t3.Emp_ID = t2.Manager_ID
left join tmp t4 on t4.Emp_ID = t3.Manager_ID
left join tmp t5 on t5.Emp_ID = t4.Manager_ID;

【讨论】:

  • 它不会总是 4 级深度.. 它是动态的.. 也可以是 10 级或更多..
【解决方案3】:

枢轴选项:

SELECT * FROM
(
  SELECT emp_id, name, manager_id
  FROM employees
)
PIVOT
(
  COUNT(manager_id)
  FOR manager_id IN ('005', '100', '050')
)
ORDER BY emp_id;

【讨论】:

  • 谢谢大家的帮助。 @Debabrata 的回答帮助我想到了最终的解决方案
猜你喜欢
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-18
  • 2014-10-27
  • 2017-05-11
  • 2019-11-24
  • 1970-01-01
相关资源
最近更新 更多