我正在尝试跟踪在递归查询中使用'in'运算符给出的第一个父级。
这是(高度简化的;-))问题:
我有一个表(myTable),带有仪器互连,如:
SENSOR_IN | SENSOR_OUT ---------------------- 5 | 6 3 | 5 7 | 8 2 | 7 1 | 2
从这个表中我想得到一个带有“level”的连接链,如:
SELECT level, sensor_in, sensor_out FROM myTable START WITH sensor_out IN (6,8) CONNECT BY sensor_out = prior sensor_in ;
这会让我感觉像[没有测试,只是为了解释]:
LEVEL | SENSOR_IN | SENSOR_OUT -------------------------------- 1 5 | 6 1 7 | 8 2 3 | 5 2 2 | 7
我想知道添加一个名为的列,让我们说“第一个”,给出作为主要父级的每一行(所以“IN()”语句中给出的值,而不是表中的“true”主要父级=>在我的特定情况下,实际上总是相同的)。因此像:
LEVEL | SENSOR_IN | SENSOR_OUT | FIRST --------------------------------------- 1 5 | 6 | 6 1 7 | 8 | 8 2 3 | 5 | 6 2 2 | 7 | 8
任何(简单)想法?
备注:如果某人有一个简单的方法可以为每个“第一个”在一行中返回整个链,那就更好了!类似的东西:
FIRST | CHAIN ------------- 8 | 8;7;2 6 | 6;5;3
提前致谢!
答案 0 :(得分:1)
您可以使用the connect_by_root
operator获取根节点:
SELECT level, sensor_in, sensor_out, connect_by_root sensor_out as first
您的示例输出无论如何都不匹配您的数据,但只需将其添加到您的查询中即可:
LEVEL SENSOR_IN SENSOR_OUT FIRST
---------- ---------- ---------- ----------
1 5 6 6
2 3 5 6
1 7 8 8
2 2 7 8
3 1 2 8
对于问题的第二部分,您可以将其用作内联视图,并使用listagg()
将值合并为一个:
SELECT first, listagg(sensor_out, ';') within group (order by lvl) as chain
FROM (
SELECT level as lvl, sensor_in, sensor_out, connect_by_root sensor_out as first
FROM myTable
START WITH sensor_out IN (6,8)
CONNECT BY sensor_out = prior sensor_in
)
GROUP BY first
ORDER BY first
;
FIRST CHAIN
---------- --------------------
6 6;5
8 8;7;2
SELECT first, chain
FROM (
SELECT connect_by_root sensor_out as first,
ltrim(sys_connect_by_path (sensor_out, ';'), ';') as chain,
connect_by_isleaf as is_leaf
FROM myTable
START WITH sensor_out IN (6,8)
CONNECT BY sensor_out = prior sensor_in
)
WHERE is_leaf = 1
;
FIRST CHAIN
---------- --------------------
6 6;5
8 8;7;2
答案 1 :(得分:1)
以下是一些您应该可以使用的功能,以获得您所追求的结果:
with mytable as (select 5 sensor_in, 6 sensor_out from dual union all
select 3 sensor_in, 5 sensor_out from dual union all
select 7 sensor_in, 8 sensor_out from dual union all
select 2 sensor_in, 7 sensor_out from dual union all
select 1 sensor_in, 2 sensor_out from dual)
SELECT level,
sensor_in,
sensor_out,
connect_by_root sensor_out top,
sys_connect_by_path (sensor_in, ';') path
FROM myTable
START WITH sensor_out IN (6,8)
CONNECT BY sensor_out = prior sensor_in;
LEVEL SENSOR_IN SENSOR_OUT TOP PATH
---------- ---------- ---------- ---------- ----------
1 5 6 6 ;5
2 3 5 6 ;5;3
1 7 8 8 ;7
2 2 7 8 ;7;2
3 1 2 8 ;7;2;1
答案 2 :(得分:1)
它可能有点冗长,但我发现递归SQL更直观,更灵活,更符合标准(因此,值得掌握,因为有一天你实际上可能使用的是非Oracle产品)而不是connect-by。证明可以轻松计算各种输出:
with mytable as (select 5 sensor_in, 6 sensor_out from dual union all
select 3 sensor_in, 5 sensor_out from dual union all
select 7 sensor_in, 8 sensor_out from dual union all
select 2 sensor_in, 7 sensor_out from dual union all
select 1 sensor_in, 2 sensor_out from dual union all
select 9 sensor_in, 10 sensor_out from dual union all
select 10 sensor_in, 9 sensor_out from dual
),
recursive_cte (first_sensor, last_sensor, forward_chain, backward_chain, chain_length, next_sensor)
as (
-- recursion base rows
select sensor_out first_sensor,
sensor_in last_sensor,
cast(sensor_out as varchar2(4000)) forward_chain,
cast(sensor_out as varchar2(4000)) backward_chain,
1 chain_length,
sensor_in next_sensor
from mytable
where sensor_out in (6,8,10)
union all
-- recursion inductive rows
select first_sensor first_sensor,
next_sensor last_sensor,
forward_chain || ';' || next_sensor forward_chain,
next_sensor || ';' || backward_chain backward_chain,
chain_length + 1 chain_length,
sensor_in next_sensor
from recursive_cte
left join mytable on sensor_out = next_sensor
where next_sensor is not null
)
cycle next_sensor set is_infinite_loop to 'Y' default 'N'
select first_sensor, last_sensor, forward_chain, backward_chain, chain_length,
is_infinite_loop
from recursive_cte
where next_sensor is null
or is_infinite_loop = 'Y'
order by first_sensor;
╔══════════════╦═════════════╦═══════════════╦════════════════╦══════════════╦══════════════════╗
║ FIRST_SENSOR ║ LAST_SENSOR ║ FORWARD_CHAIN ║ BACKWARD_CHAIN ║ CHAIN_LENGTH ║ IS_INFINITE_LOOP ║
╠══════════════╬═════════════╬═══════════════╬════════════════╬══════════════╬══════════════════╣
║ 6 ║ 3 ║ 6;5;3 ║ 3;5;6 ║ 3 ║ N ║
║ 8 ║ 1 ║ 8;7;2;1 ║ 1;2;7;8 ║ 4 ║ N ║
║ 10 ║ 10 ║ 10;9;10 ║ 10;9;10 ║ 3 ║ Y ║
╚══════════════╩═════════════╩═══════════════╩════════════════╩══════════════╩══════════════════╝