Reputation: 137
I am currently trying to get every relation & childs of any specific place of a tree. The tables are the following :
TABLE ORGANISATION TABLE LINKS
| Orga_Name | Code | DELETED | | Code | Dads_Code | STT |
| DR | DR001 | FALSE |(root) | DR001 | Null | OK |(root no dad snif)
| DSI | DS001 | FALSE | | DS001 | DR001 | OK |
| DLE | DL001 | FALSE | | DL001 | DR001 | OK |
| DMP | DM001 | FALSE | | DM001 | DS001 | OK |
| TRS | TR001 | FALSE | | TR001 | DM001 | OK |
| TRE | TE001 | TRUE | | TE001 | DM001 | NOK |
| TRC | TC001 | FALSE | | TE001 | DM001 | NOK |
If any row has either DELETED = TRUE or STT = NOK, it shouldnt be considered at all. (just like TRE and TRC in this example)
The perfect result would be like the following:
| Code | PICK-ONE| Path |
| DS001 | DR001 | DS001/DR001 |
| DL001 | DR001 | DL001/DR001 |
| DM001 | DR001 | DM001/DS001/DR001 |
| TR001 | DR001 | TR001/DM001/DS001/DR001 |
| DM001 | DS001 | DM001/DS001 |
| TR001 | DS001 | TR001/DM001/DS001 |
| TR001 | DM001 | DM001/TR001 |
So I can select a code in 'PICK-ONE' and get all the (direct & indirect) children of it as a list. I have been trying to use CONNECT_BY_ROOT, here's the current code I am using :
SELECT Code,
CONNECT_BY_ROOT Code,
LEVEL-1,
SYS_CONNECT_BY_PATH(Code, '/') "Path"--,STT
FROM (
SELECT o1.*,a1.STT,o1.DELETED
FROM ORGANISATION o1
LEFT JOIN LINKS a1
ON o1.Code=a1.Code
AND DELETED = 'FALSE'
)
WHERE LEVEL > 0 AND STT like 'OK'
CONNECT BY PRIOR Code = Dads_Code;
I am getting results mostly from the root, and one of his (always the same) children. In my example, the result I get would be from DS001 and DR001. Some of the results are correct. sadly the analyze stops at 2 level maximum,there are some duplicates, and also some path to itself results (with 0 as level).
I have been trying to change Level or path, or change some conditions, but I am unable to find the problem. I would be glad if you could help me!
Upvotes: 0
Views: 27
Reputation: 48770
Don't use CONNECT BY
since it's mostly obsolete at this point. It was a good way of querying hierarchies back in the day where there wasn't anything standard.
Use a Recursive Common Table Expression (aka Recursive CTE) available in most databases as part of the SQL standard.
For example if you want to retrieve all children of DR001
, you can do:
with n (code, dads_code, lvl, path) as (
select code, dads_code, 1, code from links where code = 'DR001'
union all
select l.code, l.dads_code, n.lvl + 1, n.path || '/' || l.code
from links l
join n on n.code = l.dads_code
where l.stt <> 'NOK'
and not exists (select 1 from organisation o
where o.code = l.code and deleted = 'TRUE')
)
select code, dads_code, lvl, path from n
Upvotes: 1