पहले माता-पिता को रिकर्सिव में रखें (प्रारंभ करें ... इन ..., कनेक्ट करें) - एसक्यूएल, ऑरैकल, रिकर्सन

मैं एक पुनरावर्ती क्वेरी में "इन" ऑपरेटर के साथ दिए गए पहले माता-पिता का ट्रैक रखने की कोशिश कर रहा हूं।

यहां (अत्यधिक सरलीकृत ;-)) समस्या है:

मेरे पास एक टेबल (myTable) है जिसमें उपकरण इंटरकनेक्शन हैं:

सेंसर इन | सेंसर आउट
----------------------
5 | 6
3 | 5
7 | 8
2 | 7
1 | 2

इस तालिका से मैं "स्तर" के साथ एक कनेक्शन श्रृंखला प्राप्त करना चाहता हूं जैसे:

चयन स्तर, सेंसर_इन, सेंसर_आउट
MyTable से
सेंसर_आउट में शुरू करें (6,8)
Sensor_out = पूर्व सेंसर_इन से कनेक्ट करें
;

वह मुझे कुछ वापस कर देगा [परीक्षण नहीं किया गया, बस व्याख्या करने के लिए]:

स्तर | सेंसर | SENSOR_OUT
--------------------------------
1 5 | 6
1 7 | 8
2 3 | 5
2 2 | 7

मैं जानना चाहता हूं कि कॉलम जोड़ें, चलो कहें"पहला", प्रत्येक पंक्ति जो प्राथमिक माता-पिता है (इसलिए "IN ()" कथन में दिया गया मान, तालिका में "सत्य" प्राथमिक अभिभावक नहीं है>> वास्तव में हमेशा मेरे विशेष मामले में समान होता है) । इस प्रकार कुछ ऐसा है:

स्तर | सेंसर | SENSOR_OUT |प्रथम
---------------------------------------
1 5 | 6 | 6
1 7 | 8 | 8
2 3 | 5 | 6
2 2 | 7 | 8

कोई भी (सरल) विचार?

टिप्पणी: अगर किसी के पास "चेन" के लिए एक पंक्ति में पूरी श्रृंखला को वापस करने का एक आसान तरीका है, तो यह भी बेहतर है! कुछ ऐसा है:

पहला | जंजीर
-------------
8 | 8, 7, 2
6 | 6; 5, 3

अग्रिम में धन्यवाद!

उत्तर:

उत्तर № 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

यह थोड़ा और वर्बोज़ हो सकता है, लेकिन मुझे लगता हैरिकर्सिव एसक्यूएल अधिक अंतर्ज्ञानी, लचीला, और मानक-अनुरूप होने के लिए (इसलिए, मास्टरिंग के लायक है क्योंकि किसी दिन आप वास्तव में गैर-ओरेकल उत्पाद का उपयोग कर सकते हैं) कनेक्ट-बाय से। आसानी से प्रदर्शन करना जिसके साथ विभिन्न आउटपुट की गणना की जा सकती है:

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                ║
╚══════════════╩═════════════╩═══════════════╩════════════════╩══════════════╩══════════════════╝

जवाब के लिए 0 № 3

आप उपयोग कर सकते हैं the connect_by_root ऑपरेटर रूट नोड प्राप्त करने के लिए:

SELECT level, sensor_in, sensor_out, connect_by_root sensor_out as first

आपके उदाहरण आउटपुट doesn "t आप डेटा वैसे भी मैच, लेकिन सिर्फ अपनी क्वेरी के लिए जोड़ देता है:

     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

एसक्यूएल फिडल

या प्रयोग कर रहे हैं अधिक pseudocolumns:

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

अभी तक एक और एसक्यूएल सारंगी


संबंधित सवाल
सबसे लोकप्रिय