Connect by in Oracle SQL
CONNECT BY PRIOR empno = manager_id;
This will produce the recursion. All records that are part of the next lower hierarchical level will return. This will return a hierarchy from top to bottom for all managers and their respective under working subordinates.
30 (manager_id)
12
5 (manager_id)
1
7
20 (manager_id)
15
10
Oracle Connect By
It seems cycles are the problem.
Cycles are detected by looking at the columns with the PRIOR operator in the CONNECT BY clause.
To break such cycles, you need to add conditions that are trivially true but use the PRIOR operator on additional columns.
For example: to your CONNECT BY clause, add
and prior emp_id is not null
(assuming that emp_id can never be null).
Display immediate parent after CONNECT_BY_ROOT in Oracle PL SQL
You can use conditional sys_connect_by_path:
rtrim(sys_connect_by_path(case when level<=2 then id else null end, '.'),'.')
Oracle connect by including a stop criteria
You can use Recursive subquery factoring to stop all searching like this:
with h(it,art,match,anymatch) as
(select item, assembly
, case when attr1 = 'marker' then 1 else 0 end
, max(case when attr1 = 'marker' then 1 else 0 end) over()
from articles
where component = '0815'
union all
select item, assembly
, case when attr1 = 'marker' then 1 else 0 end
, max(case when attr1 = 'marker' then 1 else 0 end) over()
from h, articles
where art = component
and anymatch = 0)
cycle art set cycle to 1 default 0
select it item
from h
where match = 1
and cycle = 0
It will return all matches that are found on a smallest possible level.
However as it is breadth first search, it will not be much faster if the first found marker
is deep.
Changing condition anymatch = 0
to match = 0
(anymatch
would not need to be calculated anymore) would stop only searching down the branch the match is on.
START WITH and CONNECT BY in Oracle SQL
Why not simply:
SELECT level, * FROM accounts
START WITH parent_account_id = account_id
CONNECT BY PRIOR account_id = parent_account_id
AND account_id <> parent_account_id
?
Oracle connect by prior along with max() over partition by to remove duplicate subtree
Wrap your recursive query in another CTE and filter on that:
WITH
test_hierarchy AS (
SELECT 'a' parent, 'b' child FROM dual UNION ALL
SELECT 'b','c' FROM dual UNION ALL
SELECT 'd','e' FROM dual UNION ALL
SELECT 'e','f' FROM dual UNION ALL
SELECT 'f','g' FROM dual UNION ALL
SELECT 'f','h' FROM dual
),
recursion AS (
SELECT
parent,
child,
CONNECT_BY_ROOT child AS init_child,
LEVEL AS lvl,
CONNECT_BY_ISLEAF AS isleaf,
MAX(LEVEL) OVER(
PARTITION BY parent
) AS max_level
FROM
test_hierarchy
START WITH child IN ('c', 'b', 'e', 'f', 'h', 'g')
CONNECT BY PRIOR parent = child
)
SELECT *
FROM recursion
WHERE isleaf = 1 AND lvl = max_level
Related Topics
How to Call Scalar Function in SQL Server 2008
If I Update a View, Will My Original Tables Get Updated
Atomically Mark and Return a Group of Rows in Database
Sql - Filtering Large Tables with Joins - Best Practices
How to Select The Record with The 2Nd Highest Salary in Database Oracle
Using a View with No Primary Key with Entity
Rails Activerecord - How to Fetch Records Between Two Dates
Oracle SQL to Change Column Type from Number to Varchar2 While It Contains Data
Repeating Rows Based on Column Value in Each Row
Get Total Row Count While Paging
How to Get The First Day and The Last of Previous Month Using Sql
How to Use T-SQL Full-Text Search to Get Results Like Google
Checking for Existence of Index in Postgresql
What Is The Advantage of Using Varbinary Over Varchar Here