Reputation: 167
following query was developed on https://www.tutorialspoint.com/execute_sql_online.php and works as designed:
WITH helptab1
AS (SELECT "a" AS cust,
1 AS numb,
"m006" AS val
FROM dual
UNION ALL
SELECT "b" AS cust,
1 AS numb,
"m006" AS val
FROM dual
UNION ALL
SELECT "b" AS cust,
1 AS numb,
"m777" AS val
FROM dual
UNION ALL
SELECT "b" AS cust,
2 AS numb,
"m018" AS val
FROM dual
UNION ALL
SELECT "c" AS cust,
2 AS numb,
"m454" AS val
FROM dual
UNION ALL
SELECT "c" AS cust,
5 AS numb,
"m008" AS val
FROM dual
UNION ALL
SELECT "c" AS cust,
5 AS numb,
"m090" AS val
FROM dual
UNION ALL
SELECT "c" AS cust,
6 AS numb,
"m789" AS val
FROM dual
UNION ALL
SELECT "c" AS cust,
7 AS numb,
"m191" AS val
FROM dual
UNION ALL
SELECT "d" AS cust,
9 AS numb,
"m006" AS val
FROM dual
UNION ALL
SELECT "d" AS cust,
1 AS numb,
"m123" AS val
FROM dual
UNION ALL
SELECT "e" AS cust,
3 AS numb,
"m567" AS val
FROM dual
UNION ALL
SELECT "f" AS cust,
3 AS numb,
"m777" AS val
FROM dual
UNION ALL
SELECT "g" AS cust,
3 AS numb,
"m888" AS val
FROM dual
UNION ALL
SELECT "g" AS cust,
3 AS numb,
"m765" AS val
FROM dual
UNION ALL
SELECT "g" AS cust,
4 AS numb,
"m543" AS val
FROM dual
UNION ALL
SELECT "h" AS cust,
6 AS numb,
"m888" AS val
FROM dual
UNION ALL
SELECT "h" AS cust,
6 AS numb,
"m090" AS val
FROM dual
UNION ALL
SELECT "h" AS cust,
6 AS numb,
"m001" AS val
FROM dual
UNION ALL
SELECT "h" AS cust,
7 AS numb,
"m008" AS val
FROM dual
UNION ALL
SELECT "h" AS cust,
7 AS numb,
"m090" AS val
FROM dual),
helptab2
AS (SELECT /*+materialize */ DISTINCT cust,
numb,
val,
1 AS counter
FROM helptab1
WHERE val = "m765"),
basic (cust, numb, val, counter)
AS (SELECT DISTINCT cust,
numb,
val,
1
FROM helptab2
UNION ALL
SELECT DISTINCT hlp1.cust,
hlp1.numb,
hlp1.val,
counter + 1
FROM basic bas
join helptab1 hlp1
ON ( hlp1.cust = bas.cust
AND hlp1.numb = bas.numb )
OR ( hlp1.val = bas.val )
WHERE counter <= 10),
helptab3
AS (SELECT DISTINCT cust,
numb,
val,
counter
FROM basic
ORDER BY cust,
numb,
val)
SELECT DISTINCT cust,
numb,
val
FROM helptab3;
but there are two problems, the part "where counter <= 10" isn't really smart AND it can't be executed on Oracle (12g) Developer. what needs to be done that it's running on Oracle? and how to handle the recursive part, so there is no limit and no cycle?
Upvotes: 0
Views: 1260
Reputation: 350310
Some issues in your query:
'm765'
instead of "m765"
. The latter is interpreted as a column reference.distinct
is not allowed in recursive (second) part of a recursive query. But as you still apply a distinct
in the next with
query, you can live without it, but with a tremendous cost in performance. NB: In the first part of the query distinct
is not needed, as you already did that in helptab2
counter <= 10
to work in a recursive query, it really needs to be a join condition, not a condition in the where
clause.With those changes applied, the query works but obviously becomes very slow as the recursive part will collect many of the same records and recurses into cycles.
Cycles can be prevented with the cycle
clause following the recursive with
query:
with helptab1 as (
select 'A' as cust, 1 as numb, 'm006' as val from dual union all
select 'B' as cust, 1 as numb, 'm006' as val from dual union all
select 'B' as cust, 1 as numb, 'm777' as val from dual union all
select 'B' as cust, 2 as numb, 'm018' as val from dual union all
select 'C' as cust, 2 as numb, 'm454' as val from dual union all
select 'C' as cust, 5 as numb, 'm008' as val from dual union all
select 'C' as cust, 5 as numb, 'm090' as val from dual union all
select 'C' as cust, 6 as numb, 'm789' as val from dual union all
select 'C' as cust, 7 as numb, 'm191' as val from dual union all
select 'D' as cust, 9 as numb, 'm006' as val from dual union all
select 'D' as cust, 1 as numb, 'm123' as val from dual union all
select 'E' as cust, 3 as numb, 'm567' as val from dual union all
select 'F' as cust, 3 as numb, 'm777' as val from dual union all
select 'G' as cust, 3 as numb, 'm888' as val from dual union all
select 'G' as cust, 3 as numb, 'm765' as val from dual union all
select 'G' as cust, 4 as numb, 'm543' as val from dual union all
select 'H' as cust, 6 as numb, 'm888' as val from dual union all
select 'H' as cust, 6 as numb, 'm090' as val from dual union all
select 'H' as cust, 6 as numb, 'm001' as val from dual union all
select 'H' as cust, 7 as numb, 'm008' as val from dual union all
select 'H' as cust, 7 as numb, 'm090' as val from dual),
basic (cust,numb,val) as (
select distinct cust, numb, val
from helptab1
where val = 'm765'
union all
select hlp1.cust, hlp1.numb, hlp1.val
from basic bas
join helptab1 hlp1
on hlp1.cust = bas.cust and hlp1.numb = bas.numb
or hlp1.val = bas.val)
cycle cust, numb, val set cycle to 1 default 0
select distinct cust, numb, val
from basic;
This can also be done with the alternative connect by
syntax for hierarchical queries, which has the nocycles
option:
with helptab1 as (
select 'A' as cust, 1 as numb, 'm006' as val from dual union all
select 'B' as cust, 1 as numb, 'm006' as val from dual union all
select 'B' as cust, 1 as numb, 'm777' as val from dual union all
select 'B' as cust, 2 as numb, 'm018' as val from dual union all
select 'C' as cust, 2 as numb, 'm454' as val from dual union all
select 'C' as cust, 5 as numb, 'm008' as val from dual union all
select 'C' as cust, 5 as numb, 'm090' as val from dual union all
select 'C' as cust, 6 as numb, 'm789' as val from dual union all
select 'C' as cust, 7 as numb, 'm191' as val from dual union all
select 'D' as cust, 9 as numb, 'm006' as val from dual union all
select 'D' as cust, 1 as numb, 'm123' as val from dual union all
select 'E' as cust, 3 as numb, 'm567' as val from dual union all
select 'F' as cust, 3 as numb, 'm777' as val from dual union all
select 'G' as cust, 3 as numb, 'm888' as val from dual union all
select 'G' as cust, 3 as numb, 'm765' as val from dual union all
select 'G' as cust, 4 as numb, 'm543' as val from dual union all
select 'H' as cust, 6 as numb, 'm888' as val from dual union all
select 'H' as cust, 6 as numb, 'm090' as val from dual union all
select 'H' as cust, 6 as numb, 'm001' as val from dual union all
select 'H' as cust, 7 as numb, 'm008' as val from dual union all
select 'H' as cust, 7 as numb, 'm090' as val from dual),
basic as (
select cust, numb, val
from helptab1
connect by nocycle
prior cust = cust and prior numb = numb
or prior val = val
start with val = 'm765')
select distinct cust, numb, val
from basic;
Upvotes: 1