【问题标题】:oracle sql create recursive hierarchy from textoracle sql从文本创建递归层次结构
【发布时间】:2022-01-25 20:09:54
【问题描述】:

如何仅使用这样的文本从列创建层次结构。

这是我要为其创建层次结构的示例查询。 级别是未定义的,所以它应该是一个递归语句。

select 'MP_STAGE1' mapping_name, 'table_a' target_table, 'input' inout from dual
UNION ALL
select 'MP_STAGE1' mapping_name, 'table_b' target_table, 'input' inout from dual
UNION ALL
select 'MP_STAGE1' mapping_name, 'table_c' target_table, 'output' inout from dual
UNION ALL
select 'MP_STAGE2' mapping_name, 'table_aa' target_table, 'input' inout from dual
UNION ALL
select 'MP_STAGE2' mapping_name, 'table_dd' target_table, 'output' inout from dual
UNION ALL

select 'MP_CORE1' mapping_name, 'table_c' target_table, 'input' inout from dual
UNION ALL
select 'MP_CORE1' mapping_name, 'table_dd' target_table, 'input' inout from dual
UNION ALL
select 'MP_CORE1' mapping_name, 'table_ee' target_table, 'output' inout from dual
UNION ALL

select 'MP_CORE2' mapping_name, 'table_a' target_table, 'input' inout from dual
UNION ALL
select 'MP_CORE2' mapping_name, 'table_b' target_table, 'input' inout from dual
UNION ALL
select 'MP_CORE2' mapping_name, 'table_dd' target_table, 'input' inout from dual
UNION ALL
select 'MP_CORE2' mapping_name, 'table_ff' target_table, 'output' inout from dual
UNION ALL

select 'MP_MART1' mapping_name, 'table_b' target_table, 'input' inout from dual
UNION ALL
select 'MP_MART1' mapping_name, 'table_dd' target_table, 'input' inout from dual
UNION ALL
select 'MP_MART1' mapping_name, 'table_ee' target_table, 'input' inout from dual
UNION ALL
select 'MP_MART1' mapping_name, 'table_ff' target_table, 'input' inout from dual
UNION ALL
select 'MP_MART1' mapping_name, 'table_gg' target_table, 'output' inout from dual;

创建层次结构的查询结果:

MAPPING_NAME    TARGET_TABLE    INOUT
MP_STAGE1       table_a         input
MP_STAGE1       table_b         input
MP_STAGE1       table_c         output
MP_STAGE2       table_aa        input
MP_STAGE2       table_dd        output
MP_CORE1        table_c         input
MP_CORE1        table_dd        input
MP_CORE1        table_ee        output
MP_CORE2        table_a         input
MP_CORE2        table_b         input
MP_CORE2        table_dd        input
MP_CORE2        table_ff        output
MP_MART1        table_b         input
MP_MART1        table_dd        input
MP_MART1        table_ee        input
MP_MART1        table_ff        input
MP_MART1        table_gg        output

目标 1:

MAPPING_NAME    TARGET_TABLE    INOUT   hierarchy 
MP_STAGE1       table_a         input   1
MP_STAGE1       table_b         input   1
MP_STAGE1       table_c         output  2
MP_STAGE2       table_aa        input   1
MP_STAGE2       table_dd        output  2
MP_CORE1        table_c         input   2
MP_CORE1        table_dd        input   2
MP_CORE1        table_ee        output  3
MP_CORE2        table_a         input   1
MP_CORE2        table_b         input   1
MP_CORE2        table_dd        input   2
MP_CORE2        table_ff        output  3
MP_MART1        table_b         input   1
MP_MART1        table_dd        input   2
MP_MART1        table_ee        input   3
MP_MART1        table_ff        input   3
MP_MART1        table_gg        output  4

更好地实现这个目标2:

MAPPING_NAME PARENT_TARGET_TABLE TARGET_TABLE MP_STAGE1 table_a table_c MP_STAGE1 表_b 表_c MP_STAGE2 table_aa table_dd MP_CORE1 table_c table_ee MP_CORE1 table_dd table_ee MP_CORE2 table_a table_ff MP_CORE2 表_b 表_ff MP_CORE2 table_dd table_ff MP_MART1 表_b 表_gg MP_MART1 table_dd table_gg MP_MART1 table_ee table_gg MP_MART1 表_ff 表_gg

【问题讨论】:

  • 请编辑你的问题解释你的逻辑。
  • “更好地实现”是parent_.mapping_name = child_.mapping_name and parent_.inout = 'input' and child_.inout = 'output' 上的简单自加入。下面是一个更好的答案,它在一次表扫描中做同样的事情,但需要仔细阅读才能理解逻辑。

标签: sql oracle hierarchy


【解决方案1】:

您可以使用条件聚合:

SELECT mapping_name,
       parent_target_table,
       target_table
FROM   (
  SELECT mapping_name,
         target_table AS parent_target_table,
         MAX(CASE inout WHEN 'output' THEN target_table END)
           OVER (PARTITION BY mapping_name) AS target_table,
         inout
  FROM   table_name
)
WHERE  inout = 'input';

或分层查询:

SELECT mapping_name,
       PRIOR target_table AS parent_target_table,
       target_table
FROM   table_name
WHERE  LEVEL = 2
START WITH inout = 'input'
CONNECT BY
       PRIOR mapping_name = mapping_name
AND    PRIOR inout = 'input'
AND    inout = 'output';

或者,来自 Oracle 12,MATCH_RECOGNIZE

SELECT *
FROM   table_name
MATCH_RECOGNIZE(
  PARTITION BY mapping_name
  ORDER     BY inout, target_table
  MEASURES
    FIRST(input.target_table) AS parent_target_table,
    output.target_table AS target_table
  AFTER MATCH SKIP TO NEXT ROW
  PATTERN ( input+ output $ )
  DEFINE
    input  AS inout = 'input',
    output AS inout ='output'
)

其中,对于样本数据:

CREATE TABLE table_name (mapping_name, target_table, inout) AS
SELECT 'MP_STAGE1', 'table_a',  'input'  FROM DUAL UNION ALL
SELECT 'MP_STAGE1', 'table_b',  'input'  FROM DUAL UNION ALL
SELECT 'MP_STAGE1', 'table_c',  'output' FROM DUAL UNION ALL
SELECT 'MP_STAGE2', 'table_aa', 'input'  FROM DUAL UNION ALL
SELECT 'MP_STAGE2', 'table_dd', 'output' FROM DUAL UNION ALL
SELECT 'MP_CORE1',  'table_c',  'input'  FROM DUAL UNION ALL
SELECT 'MP_CORE1',  'table_dd', 'input'  FROM DUAL UNION ALL
SELECT 'MP_CORE1',  'table_ee', 'output' FROM DUAL UNION ALL
SELECT 'MP_CORE2',  'table_a',  'input'  FROM DUAL UNION ALL
SELECT 'MP_CORE2',  'table_b',  'input'  FROM DUAL UNION ALL
SELECT 'MP_CORE2',  'table_dd', 'input'  FROM DUAL UNION ALL
SELECT 'MP_CORE2',  'table_ff', 'output' FROM DUAL UNION ALL
SELECT 'MP_MART1',  'table_b',  'input'  FROM DUAL UNION ALL
SELECT 'MP_MART1',  'table_dd', 'input'  FROM DUAL UNION ALL
SELECT 'MP_MART1',  'table_ee', 'input'  FROM DUAL UNION ALL
SELECT 'MP_MART1',  'table_ff', 'input'  FROM DUAL UNION ALL
SELECT 'MP_MART1',  'table_gg', 'output' FROM DUAL;

所有输出:

MAPPING_NAME PARENT_TARGET_TABLE TARGET_TABLE
MP_CORE1 table_c table_ee
MP_CORE1 table_dd table_ee
MP_CORE2 table_dd table_ff
MP_CORE2 table_b table_ff
MP_CORE2 table_a table_ff
MP_MART1 table_ff table_gg
MP_MART1 table_ee table_gg
MP_MART1 table_dd table_gg
MP_MART1 table_b table_gg
MP_STAGE1 table_a table_c
MP_STAGE1 table_b table_c
MP_STAGE2 table_aa table_dd

db小提琴here

【讨论】: