Recursive/Hierarchical Query
Hello,
I am trying to solve a problem that needs the use of recursive queries (more precisely the "connect by" clause). I have the following P table:
P1 P2
a1 a2
a1 a3
a2 a4
a3 a5
a4 a6
The result of my query should be:
P1 P2
a1 a2
a1 a3
a1 a4
a1 a5
a1 a6
a2 a4
a2 a6
As you can see, I am trying to get all the children, grandchildren, etc of every P1, going to the deepest level possible, following the transitivity property (if a1-a2, and a2-a4, then "a1 a4" will be part of the solution). The following query
select distinct P1, P2 from P
connect by P2 = prior P1
order by P1
gives me only the first level of inclusions (a1 a2, a1 a3, a2...), but I need all of them. How can I solve the problem?
Thank you!
In a 10g environment you can use the CONNECT_BY_ROOT operatory to get the root node:
WITH P AS (SELECT 'a1' P1,'a2' P2 FROM DUAL
UNION ALL SELECT 'a1', 'a3' FROM DUAL
UNION ALL SELECT 'a2', 'a4' FROM DUAL
UNION ALL SELECT 'a3', 'a5' FROM DUAL
UNION ALL SELECT 'a4', 'a6' FROM DUAL
SELECT DISTINCT CONNECT_BY_ROOT P1 P1, P2
FROM P CONNECT BY P1 = PRIOR P2
ORDER BY P1,P2
P1 P2
a1 a2
a1 a3
a1 a4
a1 a5
a1 a6
a2 a4
a2 a6
a3 a5
a4 a6
9 rows selected
Similar Messages
-
Recursive Hierarchical Query with CONNECT BY/START WITH
I want to traverse a tree which has is not hierarchical in linear sense. You know, like :
A
B
C
D
E
C
F
D
E
C
You see that D, Eand C are repeated and C is under E as well as under B. I tried using CONNECT BY and START WITH but I get tripliate occurances of C under B, and 2 occurances of DEC under A and under F. Clearly this is not correct. I believe SQL3 has special way of handling with such recursive trees. How does O9i handle these constructs? Please help.CREATE OR REPLACE PACKAGE hierarchy
IS
TYPE branchtable_type IS TABLE OF VARCHAR2 (4000)
INDEX BY BINARY_INTEGER;
branchtable branchtable_type;
FUNCTION branch
(v_level IN NUMBER,
v_value IN VARCHAR2,
v_delimeter IN VARCHAR2 DEFAULT CHR (0))
RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES (branch, WNDS);
END hierarchy;
CREATE OR REPLACE PACKAGE BODY hierarchy
IS
returnvalue VARCHAR2 (4000);
FUNCTION branch
(v_level IN NUMBER,
v_value IN VARCHAR2,
v_delimeter IN VARCHAR2 DEFAULT CHR (0))
RETURN VARCHAR2
IS
BEGIN
branchtable (v_level) := v_value;
returnvalue := v_value;
FOR i IN REVERSE 1 .. v_level - 1
LOOP
returnvalue := branchtable (i)
|| v_delimeter
|| returnvalue;
END LOOP;
RETURN returnvalue;
END branch;
END hierarchy;
SELECT id, parent_id, print_order, lvl
FROM (SELECT id, parent_id, print_order, LEVEL lvl,
hierarchy.branch (LEVEL, print_order) branch
FROM test_table
START WITH parent_id IS NULL
CONNECT BY PRIOR id = parent_id)
ORDER BY branch
ID PARENT_ID PRINT_ORDER LVL
1 1 1
6 1 1 2
5 1 2 2
2 1 3 2
4 2 1 3
3 2 2 3
6 rows selected. -
Recursive Sub-query Factoring vs Hierarchical Query
Experts,
The below are two queries i am executing by using classical approach hierarchical and newest recursive sub-query.Problem is output was different for recursive sub-query factoring, as this is not showing parent-child approach, while connect by prior is showing parent-child fashion.Query 1, i am using hierarchical as it showing correct output parent-child approach, while Query 2 is displaying all the level 1 nodes and then level 2 nodes.I want query 2 output to be same as query 1.Please modify query 2 as required.
Note:The output of the both queries won't be in displayed as it was in sqlplus, or toad.Please copy and use in your command prompts.
QUERY 1:
with main as(select 1 id,'john' name,null mgrid from dual union all
select 2 id,'michael' name,null mgrid from dual union all
select 3 id,'peter' name,null mgrid from dual union all
select 4 id,'henry' name,1 mgrid from dual union all
select 5 id,'nick' name,2 mgrid from dual union all
select 6 id,'pao' name,3 mgrid from dual union all
select 7 id,'kumar' name,3 mgrid from dual union all
select 8 id,'parker' name,3 mgrid from dual union all
select 9 id,'mike' name,5 mgrid from dual),
select lpad(' ',2*(level-1))||name name,level from main start with mgrid is null connect by prior id=mgrid;
OUTPUT :
NAME LEVEL
john 1
henry 2
michael 1
nick 2
mike 3
peter 1
pao 2
kumar 2
parker 2
9 rows selected.
QUERY 2:
with main as(select 1 id,'john' name,null mgrid from dual union all
select 2 id,'michael' name,null mgrid from dual union all
select 3 id,'peter' name,null mgrid from dual union all
select 4 id,'henry' name,1 mgrid from dual union all
select 5 id,'nick' name,2 mgrid from dual union all
select 6 id,'pao' name,3 mgrid from dual union all
select 7 id,'kumar' name,3 mgrid from dual union all
select 8 id,'parker' name,3 mgrid from dual union all
select 9 id,'mike' name,5 mgrid from dual),
/*select lpad(' ',2*(level-1))||name name,level from main start with mgrid is null connect by prior id=mgrid;*/
secmain (id,name,mgrid,hierlevel) as(select id,name,mgrid,1 hierlevel from main where mgrid is null
union all
select m.id,m.name,m.mgrid,sm.hierlevel+1 from main m join secmain sm on(m.mgrid=sm.id))
cycle id set is_cycle to 1 default 0
select lpad(' ',2*(hierlevel-1))||name name,hierlevel from secmain;
OUTPUT :
NAME HIERLEVEL
john 1
michael 1
peter 1
henry 2
nick 2
parker 2
kumar 2
pao 2
mike 3
9 rows selected.Hi,
What's wrong with Query 1? If it's producing the results you want, then why not use it?
One of the nice features of CONNECT BY is that the output is automatically presented in hierachical order. The only way I know of to get the results of a recursive WITH clause in any kind or order is to do it yourself. Here's one way:
WITH secmain (id, name, mgrid, hierlevel, path) AS
SELECT id
, name
, mgrid
, 1 AS hierlevel
, RPAD (name, 10) AS path -- Assuming name is never longer than 10
FROM main
WHERE mgrid IS NULL
UNION ALL
SELECT m.id
, m.name
, m.mgrid
, sm.hierlevel + 1
, sm.path || RPAD (name, 10)
FROM main m
JOIN secmain sm ON (m.mgrid = sm.id)
CYCLE id -- Why do you need this if CONNECT BY NOCYCLE wasn't needed in Query 1?
SET is_cycle TO 1
DEFAULT 0
SELECT lpad ( ' '
, 2 * (hierlevel - 1)
) || name AS name
, hierlevel
FROM secmain
ORDER BY path
;Sorry, I don't have an Oracle 11.2 database right now, so I can't test it.
Edited by: Frank Kulash on Nov 23, 2011 9:15 AM
I didn't know about the SEARCH clause, Use Dom's solution, above. -
A help with a hierarchical query
I've got two tables:
FOLDERS where relevant fields are: folderId, parentFolderId, folderQuota
and DOCUMENTS where the relevant fields are: folderId, size
FOLDERS is hierarchical - parentFolderId of a child's folder is set to folderId of the parent
folderQuota is nullable (quota not set)
Now, I need to execute a query with the following recursive logic
<i>function calcQuota (folderIdpar, isFirstpar) {
if (not isFirstpar) and (folderQuota of folder with folderIdpar is not null) return folderQuota;
return size of all documents where folderId = folderIdpar + calcQuota (folderId of all children, false);
}</i>
(I hope the pseudocode is understandable - the query is executed as <i>calcQuota(originalFolderId, true)</i>).
Now, my question is if I can achieve it with a single hierarchical query, or if I have to implement it as a recursive stored procedure.
Thanks!
P.S. I'm using Oracle XE (10g)OK,
I will need to create it (in real life it is created by an application), so I hope I will make it correct. If not, it should be easy to fix.
create table folders (
folder_id number primary key
parent_folder_id number,
quota number
create table documents (
document_id number primary key
folder_id number,
size number
INSERT INTO folders (folder_id, quota) VALUES (1, 1);
INSERT INTO folders (folder_id, parent_folder_id, quota) VALUES (2, 1, 2);
INSERT INTO folders (folder_id, parent_folder_id) VALUES (3, 1);
INSERT INTO folders (folder_id, parent_folder_id, quota) VALUES (4, 2, 4);
INSERT INTO folders (folder_id, parent_folder_id) VALUES (5, 2);
INSERT INTO folders (folder_id, parent_folder_id, quota) VALUES (6, 3, 8);
INSERT INTO folders (folder_id, parent_folder_id) VALUES (7, 3);
INSERT INTO documents (document_id, folder_id, size) VALUES (1, 1, 16);
INSERT INTO documents (document_id, folder_id, size) VALUES (2, 2, 32);
INSERT INTO documents (document_id, folder_id, size) VALUES (3, 3, 64);
INSERT INTO documents (document_id, folder_id, size) VALUES (4, 3, 128);
INSERT INTO documents (document_id, folder_id, size) VALUES (5, 4, 256);
INSERT INTO documents (document_id, folder_id, size) VALUES (6, 5, 512);
INSERT INTO documents (document_id, folder_id, size) VALUES (7, 6, 1024);
INSERT INTO documents (document_id, folder_id, size) VALUES (8, 7, 2048);
running the query for folder_id = 1 should return 1 + 2 + 64 + 128 + 8 + 2048 = 2251
running the query for folder_id = 2 should return 4 + 512 = 516
I have decided for this data, because it allows to track what values (folder.quota or document.size) is included in the result.
(it is the knapsack problem - see http://en.wikipedia.org/wiki/Knapsack_problem)
P.S. I'm leaving for three weeks, so I will come back after that. -
Is it possible to implement Recursive CTE query in MDX to Cube dataset?
I have data with hierarchical relationship like this:
Release -> Features -> PBI/Bugs -> Tasks/Test Case. I have two datasets Work Item and Work Item Linked to get this hierarchical information.
The data looks like this:
Something like if I pass a Release ID, I need to get all the children and sub-children also. Basically a report like this:
I did this by implementing a recursive CTE query with warehouse tables. But it takes more time to load. SO trying to find the possibility using MDX and querying the cube datasetsHello,
There is nothing stopping you from querying the cache to see what is in it. However, this will only take into account items that are already in the cache. If you need a query to return items that are potentially not in the cache, you need to query the database, have the query return keys, and then request those keys through Coherence - which will in turn pull the items from the database as needed.
Regards,
-Dave -
Hi,
I have a hierarchical query which takes 2 seconds to execute. I need to get this down to milli seconds.
The table has around 8000 records. The query will never return more than 20 or so records. There is only ever 2 levels to the query.
I am quite surprised at this because it is a very simple query no table joins etc and I would have though 8000 records was nothing for Oracle.
Select id, parent_id, col1, col2, col3, col4, col5, col6
from my_table
where id=500
start with parent_id is null
connect by prior id = parent_id;
I have even tried initializing the start with say with 0 and making it a not null column...... indexing the columns used in the start with + connect by
I have tried various indexing stratergies. Does anyone have any similar experience? I am using Oracle 9i.
Thanks in advanceHow can I utilise the above query in a view if at all? Will I be able to pass in differnt ID's to the START WITH...?Certainly, you can. For example, you can use packaged
public variable to pass a parameter or Oracle CONTEXT:
SQL> create or replace package pass_param is
2 empno emp.empno%TYPE;
3 function get_empno return emp.empno%TYPE;
4 end;
5 /
 
Package created.
 
SQL> create or replace package body pass_param is
2 function get_empno return emp.empno%TYPE
3 is
4 begin
5 return empno;
6 end;
7 end;
8 /
 
Package body created.
 
SQL> create or replace view emp_v as
2 select ename from emp
3 start with empno = pass_param.get_empno
4 connect by prior empno = mgr
5 /
 
View created.
 
SQL> exec pass_param.empno := 7839;
 
PL/SQL procedure successfully completed.
 
SQL> select * from emp_v;
 
ENAME
KING
JONES
SCOTT
ADAMS
FORD
SMITH
BLAKE
ALLEN
WARD
MARTIN
TURNER
JAMES
CLARK
MILLER
 
14 rows selected.
 
SQL> exec pass_param.empno := 7698;
 
PL/SQL procedure successfully completed.
 
SQL> select * from emp_v;
 
ENAME
BLAKE
ALLEN
WARD
MARTIN
TURNER
JAMES
 
6 rows selected. or:
SQL> create or replace package set_param
2 is
3 procedure set_empno(empno in number);
4 end;
5 /
 
Package created.
 
SQL> create or replace package body set_param
2 is
3 procedure set_empno(empno in number)
4 is
5 begin
6 dbms_session.set_context('empnamespace','empno',empno);
7 end;
8 end;
9 /
 
Package body created.
 
SQL> create or replace context empnamespace using set_param;
 
Context created.
 
SQL> create or replace view emp_v as
2 select ename from emp
3 start with empno = sys_context('empnamespace','empno')
4 connect by prior empno = mgr
5 /
 
View created.
 
SQL> exec set_param.set_empno(7698);
 
PL/SQL procedure successfully completed.
 
SQL> select * from emp_v;
 
ENAME
BLAKE
ALLEN
WARD
MARTIN
TURNER
JAMES
 
6 rows selected.
 
SQL> exec set_param.set_empno(7839);
 
PL/SQL procedure successfully completed.
 
SQL> select * from emp_v;
 
ENAME
KING
JONES
SCOTT
ADAMS
FORD
SMITH
BLAKE
ALLEN
WARD
MARTIN
TURNER
JAMES
CLARK
MILLER
 
14 rows selected.Rgds. -
Too many results in hierarchically query
Hello all,
I'm searching for an idea to stop getting results 2, 3 and more times out of the following query
select
t.lvl,
t.syswflvl,
t.upper,
LPAD(' ', (lvl)*8)||t.code code,
LPAD(' ', (lvl)*8)||t.bezeichnung bezeichnung,
t.chk,
t.rang
from (
select '0' lvl, '0-'||to_char(syswftable,'0000000') syswflvl, '0- 0000000' upper, syscode code, bezeichnung, '' chk, 0 rang from wftable where (select count(wfm.syswftable) from wfm where wfm.syswftable = wftable.syswftable) > 0 union
select '1' lvl, '1-'||to_char(syswfm,'0000000') syswflvl, '0-'||to_char(syswftable,'0000000') upper, syscode code, kurzbez bezeichnung, anzeigefilter chk, 1 rang from wfm union
select '2' lvl, '2-'||to_char(syswfa,'0000000') syswflvl, '1-'||to_char(syswfm,'0000000') upper, syscode code, kurzbez bezeichnung, bedingung chk, rang from wfa union
select '3' lvl, '3-'||to_char(syswfc,'0000000') syswflvl, '2-'||to_char(syswfa,'0000000') upper, syscode code, kurzbez bezeichnung, bedingung chk, rang from wfc union
select '4' lvl, '4-'||to_char(syswfg,'0000000') syswflvl, '3-'||to_char(syswfc,'0000000') upper, syscode code, kurzbez bezeichnung, bedingung chk, rang from wfg
) t
where ((t.chk not like '%and 0%'
and trim(t.chk) not like '0%')
or t.chk is null)
and upper not like '%-'
connect by nocycle prior syswflvl = upper
order siblings by upper, syswflvl, rang
What happens is, that I get the results from level 0 one times, from level 1 two times, from level 2 three times etc.
What I'm try to achive is to get only the whole thing once.
Hope you can see what my problem is ;-)
Regards
CarstenThe effect of not having a start with clause in a hierarchical query is that a hierarchy is produced starting at every possible entry-point. So, you'll get the hierachy from node 1, the hierarchy from all nodes 2, the hierarchy from all nodes 3 and so one. Whether it starts with the correct one or not is not really relevant, as you already figured out that you get too much....
So, just believe it, add a start with clause...and your problems are gone. -
Value of the start in the Select with in a Hierarchical Query
Exist any way for put in the select the value of the start with in a Hierarchical Query?
An example:
I'll need sth like
CTH@> select n code, level, np code_parent, 1 code_first_parent
2 from demo
3 start with n=1
4 connect by np = prior n
5 ;
CODE LEVEL CODE_PARENT CODE_FIRST_PARENT
1 1 1
2 2 1 1
3 3 2 1
4 4 3 1
5 5 4 1
6 6 5 1
7 7 6 1
8 8 7 1
9 9 8 1
10 10 9 1
-- Naturally it couldn´t be a constant value
The query
select n,d, level nivel
, np, prior n
from demo
start with n=1
connect by np = prior n
--Table and inserts
create table demo
( n number,
d varchar2(5),
np number);
insert into demo values (1,'A', null);
insert into demo values (2,'B',1);
insert into demo values (3,'C',2);
insert into demo values (4,'D',3);
insert into demo values (5,'E',4);
insert into demo values (6,'F',5);
insert into demo values (7,'G',6);
insert into demo values (8,'H',7);
insert into demo values (9,'I',8);
insert into demo values (10,'J',9);
insert into demo values (11,'K', null);
insert into demo values (12,'L',11);
insert into demo values (13,'M',12);
insert into demo values (14,'N',13);
insert into demo values (15,'O',14);
insert into demo values (16,'P',15);
Message was edited by:
cthOn 10g
connect_by_root(n)Best regards
Maxim -
[Oracle 8i] Need help pruning branches from a hierarchical query
My problem is that my hierarchical query seems only to trim out the values that don't meet my criteria, but still includes their children. When my query hits a record that does not meet my criteria, I want it to stop there. I've tried including the criteria in just the 'where' clause of the query, and have also put the criteria in the 'connect by' clause as well, but nothing has fixed it. Please keep in mind I'm using Oracle 8i, so I can't use some of the 'nicer' statements for hierarchical queries that they introduced in 9. I'm stuck with 'Start With...Connect By'.
I have sample tables/data that I can post if someone needs to see that to help me, but to start with, here's my current query:
SELECT *
FROM (
SELECT
LEVEL
, c_bill.comp_part_nbr AS c_part_nbr
, (select c_part.part_desc
FROM part c_part
WHERE c_part.part_nbr=c_bill.comp_part_nbr) AS c_part_desc
, (SELECT c_part.part_type
FROM part c_part
WHERE c_part.part_nbr=c_bill.comp_part_nbr) AS c_part_type
, c_bill.qty_per AS c_qty_per_p
, c_bill.qty_per_type AS c_qty_per_type
, (SELECT c_part.qty_on_hand
FROM part c_part
WHERE c_part.part_nbr=c_bill.comp_part_nbr) AS c_qty_on_hand
, c_bill.oper_nbr AS rqd_at_op
, c_bill.comp_off_adj AS rqd_offset
, c_bill.bom_doc_nbr AS p_part_nbr
, (SELECT p_part.qty_on_hand
FROM part p_part
WHERE p_part.part_nbr=c_bill.bom_doc_nbr) AS p_qty_on_hand
FROM
BILL c_bill
WHERE
(c_bill.status = 'RL')
AND (c_bill.view_code IN ('M','G'))
AND (c_bill.end_eff_dt > SYSDATE)
AND (c_bill.begn_eff_dt <= SYSDATE)
START WITH c_bill.bom_doc_nbr=RPAD(?,25)
CONNECT BY PRIOR c_bill.comp_part_nbr=c_bill.bom_doc_nbr
AND c_bill.view_code IN ('M','G')
AND c_bill.status = 'RL'
AND c_bill.end_eff_dt > SYSDATE
AND c_bill.begn_eff_dt <= SYSDATE
) a
WHERE c_part_type = 'M'The outside criterion of part_type='M' isn't my problem. Where I'm actually seeing my issue rear its ugly head is in the criterion:
(c_bill.view_code IN ('M','G'))What I'll have happen is that one of the children or grandchildren of the part number I'm querying for (my parameter), will be of some view code that's not 'M' or 'G'. In my sample data below, I have a level 4 part that is part of the 'H' view code, which I don't want, nor do I want it's children. However, its child is in the 'G' view code, and my query returns it anyway.
In my sample data below, I'm assuming that the parameter = 'XYZ-100'
CREATE TABLE part
part_nbr varchar(25) not null,
part_desc varchar(25) not null,
part_type char(1) not null,
qty_on_hand double(13,4) not null
CONSTRAINT part_pk
PRIMARY KEY (part_nbr),
CONSTRAINT check_part_type
CHECK (part_type IN ('M','P','X','Y')),
CONSTRAINT check_qty_on_hand
CHECK (qty_on_hand >= 0)
CREATE TABLE bill
row_added_ts char(20) not null,
bom_doc_nbr varchar(25) not null,
comp_part_nbr varchar(25) not null,
qty_per double(9,5) not null,
qty_per_type char(1) not null,
oper_nbr char(4) not null,
comp_off_adj double(3,0),
status char(2),
view_code char(1) not null,
end_eff_dt date() not null,
begn_eff_dt date() not null
CONSTRAINT bill_pk
PRIMARY KEY (row_added_ts),
CONSTRAINT check_qty_per_type
CHECK (qty_per_type IN ('0','1','2','3')),
CONSTRAINT check_status
CHECK (status IN ('IN', 'RL')),
); Values for those tables:
INSERT INTO part
VALUES ('xyz-1', 'purchased part', 'P', 5);
INSERT INTO part
VALUES ('xyz-2', 'purchased part', 'P', 1);
INSERT INTO part
VALUES ('xyz-3', 'purchased part', 'P', 1);
INSERT INTO part
VALUES ('xyz-3a', 'manufactured part', 'M', 1);
INSERT INTO part
VALUES ('xyz-4', 'purchased part', 'P', 1);
INSERT INTO part
VALUES ('xyz-9-1', 'manufactured part', 'M', 0);
INSERT INTO part
VALUES ('xyz-9a', 'manufactured part', 'M', 0);
INSERT INTO part
VALUES ('raw-1', 'purchased raw material', 'P', 212);
INSERT INTO part
VALUES ('raw-2', 'purchased raw material', 'P', 75.5);
INSERT INTO part
VALUES ('XYZ-100', 'manufactured part', 'M', 0);
INSERT INTO part
VALUES ('(OPEN)', '(not in use)', 'Y', 0);
INSERT INTO part
VALUES ('XYZ-100-1', 'manufactured part', 'M', 0);
INSERT INTO part
VALUES ('XYZ-100-2', 'manufactured part', 'M', 1);
INSERT INTO part
VALUES ('XYZ-100-3', 'manufactured part', 'M', 0);
INSERT INTO part
VALUES ('XYZ-100-4', 'manufactured part', 'M', 2);
INSERT INTO part
VALUES ('XYZ-100-A', 'manufactured part', 'M', 0);
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100','xyz-1',3,'1','****',0,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100','XYZ-100-1',1,'1','****',0,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-1','xyz-1',2,'1','****',1,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-1','XYZ-100-2',3,'1','****',0,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-2','xyz-2',6,'1','****',2,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-2','xyz-4',6,'1','****',2,'IN','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-2','xyz-100-3',1,'1','****',0,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-3','xyz-3',8,'1','****',1,'RL','M','01-Jan-2050','01-Jan-2000');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-3','xyz-3a',8,'1','****',1,'RL','M','01-Jan-2000','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-3','XYZ-100-4',4,'1','****',0,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-3','XYZ-100-A',2,'1','****',2,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008071153100150000','XYZ-100-3','(OPEN)',2,'1','****',0,'RL','E','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008071153100150000','XYZ-100-3','xyz-9-1',2,'1','****',0,'RL','H','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-4','raw-1',8.75,'1','****',0,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008072153100150000','XYZ-100-A','raw-2',3.75,'1','****',0,'RL','M','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008075911100150000','xyz-9-1','xyz-9a',1,'1','****',0,'RL','G','01-Jan-2050','01-Jan-1900');
INSERT INTO bill
VALUES ('2008087711100150000','xyz-9a','raw-2',3.75,'1','****',0,'RL','G','01-Jan-2050','01-Jan-1900');Sample data displayed in table format:
--PART table (from insert statements above)
part_nbr part_desc part_type qty_on_hand
xyz-1 purchased part P 5
xyz-2 purchased part P 1
xyz-3 purchased part P 1
xyz-3a manufactured part M 1
xyz-4 purchased part P 1
xyz-9-1 manufactured part M 0
xyz-9a manufactured part M 0
raw-1 purchased raw material P 212
raw-2 purchased raw material P 75.5
XYZ-100 manufactured part M 0
(OPEN) (not in use) Y 0
XYZ-100-1 manufactured part M 0
XYZ-100-2 manufactured part M 1
XYZ-100-3 manufactured part M 0
XYZ-100-4 manufactured part M 2
XYZ-100-A manufactured part M 0
--BILL table (from insert statements above)
row_added_ts bom_doc_nbr comp_part_nbr qty_per qty_per_type oper_nbr comp_off_adj status view_code end_eff_dt begn_eff_dt
2008072153100150000 XYZ-100 xyz-1 3 1 **** 0 RL G 01-Jan-2050 01-Jan-1900
2008072223100150000 XYZ-100 XYZ-100-1 1 1 **** 0 RL M 01-Jan-2050 01-Jan-1900
2008072411100150000 XYZ-100-1 xyz-1 2 1 **** 1 RL M 01-Jan-2050 01-Jan-1900
2008072459100150000 XYZ-100-1 XYZ-100-2 3 1 **** 0 RL M 01-Jan-2050 01-Jan-1900
2008072578100150000 XYZ-100-2 xyz-2 6 1 **** 2 RL M 01-Jan-2050 01-Jan-1900
2008072694100150000 XYZ-100-2 xyz-4 6 1 **** 2 IN G 01-Jan-2050 01-Jan-1900
2008072786100150000 XYZ-100-2 xyz-100-3 1 1 **** 0 RL M 01-Jan-2050 01-Jan-1900
2008072865100150000 XYZ-100-3 xyz-3 8 1 **** 1 RL M 01-Jan-2050 01-Jan-2000
2008073100100150000 XYZ-100-3 xyz-3a 8 1 **** 1 RL M 01-Jan-2000 01-Jan-1900
2008073159100150000 XYZ-100-3 XYZ-100-4 4 1 **** 0 RL M 01-Jan-2050 01-Jan-1900
2008073346100150000 XYZ-100-3 XYZ-100-A 2 1 **** 2 RL M 01-Jan-2050 01-Jan-1900
2008073478100150000 XYZ-100-3 (OPEN) 2 1 **** 0 RL E 01-Jan-2050 01-Jan-1900
2008073529100150000 XYZ-100-3 xyz-9-1 2 1 **** 0 RL H 01-Jan-2050 01-Jan-1900
2008073798100150000 XYZ-100-4 raw-1 8.75 1 **** 0 RL M 01-Jan-2050 01-Jan-1900
2008073811100150000 XYZ-100-A raw-2 3.75 1 **** 0 RL M 01-Jan-2050 01-Jan-1900
2008075911100150000 xyz-9-1 xyz-9a 1 1 **** 0 RL G 01-Jan-2050 01-Jan-1900
2008087711100150000 xyz-9a raw-2 3.75 1 **** 0 RL G 01-Jan-2050 01-Jan-1900--What I want to get with my query (branches pruned off my tree)
LEVEL C_PART_NBR C_PART_DESC C_PART_TYPE C_QTY_PER_P C_QTY_PER_TYPE C_QTY_ON_HAND RQD_AT_OP RQD_OFFSET P_PART_NBR P_QTY_ON_HAND
1 XYZ-100-1 manufactured part M 1 1 0 **** 0 XYZ-100 0
2 XYZ-100-2 manufactured part M 3 1 1 **** 0 XYZ-100-1 0
3 xyz-100-3 manufactured part M 1 1 0 **** 0 XYZ-100-2 1
4 XYZ-100-4 manufactured part M 4 1 2 **** 0 XYZ-100-3 0
4 XYZ-100-A manufactured part M 2 1 0 **** 2 XYZ-100-3 0--What I actually get with my query (includes children of items that don't meet query criteria)
LEVEL C_PART_NBR C_PART_DESC C_PART_TYPE C_QTY_PER_P C_QTY_PER_TYPE C_QTY_ON_HAND RQD_AT_OP RQD_OFFSET P_PART_NBR P_QTY_ON_HAND
1 XYZ-100-1 manufactured part M 1 1 0 **** 0 XYZ-100 0
2 XYZ-100-2 manufactured part M 3 1 1 **** 0 XYZ-100-1 0
3 xyz-100-3 manufactured part M 1 1 0 **** 0 XYZ-100-2 1
4 XYZ-100-4 manufactured part M 4 1 2 **** 0 XYZ-100-3 0
4 XYZ-100-A manufactured part M 2 1 0 **** 2 XYZ-100-3 0
5 xyz-9a manufactured part M 1 1 0 **** 0 xyz-9-1 0Edited by: user11033437 on Jul 30, 2009 7:27 AM (grammar) -
Hierarchical Query with Rollup Sum (CONNECT BY with GROUP BY ROLLUP)
Hi all,
Imagine the following scenario: i have an ACCOUNT table which holds accounts and their hierarchy (currently 5 levels), and a BALANCE table which holds balance records for the accounts. Only CHILD accounts (level 5) have records in the BALANCE table. Simple example:
CREATE TABLE accounts (account_code VARCHAR2(30), parent_account VARCHAR2(30), account_desc VARCHAR2(400));
CREATE TABLE balances (account_code VARCHAR2(30), balance_amount NUMBER(18,2));
INSERT INTO ACCOUNTS VALUES ('TOT',NULL,'Total');
INSERT INTO ACCOUNTS VALUES ('ANA1','TOT','General Expenses');
INSERT INTO ACCOUNTS VALUES ('4801001','ANA1','Small Expenses');
INSERT INTO ACCOUNTS VALUES ('4801002','ANA1','Transportation');
INSERT INTO ACCOUNTS VALUES ('ANA2','TOT','Health Expenses');
INSERT INTO ACCOUNTS VALUES ('4802001','ANA2','Healthcare');
INSERT INTO ACCOUNTS VALUES ('4802002','ANA2','Facilities');
INSERT INTO BALANCES VALUES ('4801001', 2000);
INSERT INTO BALANCES VALUES ('4801002', 1000);
INSERT INTO BALANCES VALUES ('4802001', 3000);
INSERT INTO BALANCES VALUES ('4802002', 4000);What i need in this scenario is to run a hierarchical query, where for each node i compute the sum of all its children (In LEAF nodes which are the child accounts, this sum is the value in BALANCES itself). Final Result would be:
TOT -> 10000
ANA1 -> 3000
4801001 -> 2000
4801001 -> 1000
ANA2 -> 7000
4802001 -> 3000
4802002 -> 4000I have tried various ways, and found out a workaround which works for a fixed amount of levels, basically it builds the hierarchy and computes the SYS_CONNECT_BY_PATH, then splits this as a regular expression and uses GROUP BY ROLLUP to compute the higher levels. Then i assemble it again, now with the computed values. Below is the example query:
select level
, NVL (vfinal.child_account,'TOTAL') ||' - '||
( SELECT account_desc
FROM accounts
WHERE account_code = vfinal.child_acct ) account_name
, to_char(sum_bal, 'fm999g999g999g990') as rolled_up_balance
from
select coalesce( princ.lvl3, princ.lvl2, princ.lvl1 ) child_acct
, DECODE ( princ.lvl2 , NULL
, NULL
, DECODE ( princ.conta_lvl3, NULL
, princ.conta_lvl1,princ.conta_lvl2 ) ) parent_acct
, sum(princ.balance_amount) sum_bal
from (
select hier.lvl1
, hier.lvl2
, hier.lvl3
, hier.parent_account
, hier.account_code child_acc
, bal.balance_amount
from ( select level
, sys_connect_by_path( account_code, '/' ) hierarchy_acct
, REGEXP_SUBSTR(sys_connect_by_path( account_code, '/' ),'[^/]+',1,3) lvl3
, REGEXP_SUBSTR(sys_connect_by_path( account_code, '/' ),'[^/]+',1,2) lvl2
, REGEXP_SUBSTR(sys_connect_by_path( account_code, '/' ),'[^/]+',1,1) lvl1
, account_code
, parent_account
from accounts acc
where level <= 3
start with parent_account is null
connect by nocycle prior account = parent_account
order siblings by parent_account
) hier
, balances bal
where bal.cod_conta = hier.account_code
) princ
where princ.lvl1 is not null
group by rollup ( princ.lvl1
, princ.lvl2
, princ.lvl3 )
order by princ.conta_lvl1
, princ.conta_lvl2
, princ.conta_lvl3
) vfinal
where child_acct is not null
start with parent_acct is null
connect by nocycle prior child_acct = parent_acctAll said and done, what i need is to do the same thing for infinite levels, because this query has 3 fixed levels. Do you know how can i structure a new query where, independently of the number of levels, the parent sums are all rolled up like this?
Thanks a lot in advance! Best Regards!
Thiago
Edited by: Thiago on Sep 6, 2011 11:31 AM
Edited by: Thiago on Sep 6, 2011 1:01 PMHi,
Thiago wrote:
Hi all,
Imagine the following scenario: i have an ACCOUNT table which holds accounts and their hierarchy (currently 5 levels), and a BALANCE table which holds balance records for the accounts. Only CHILD accounts (level 5) have records in the BALANCE table. Simple example:
CREATE TABLE accounts (account_code VARCHAR2(30), parent_account VARCHAR2(30), account_desc VARCHAR2(400));
CREATE TABLE balances (account_code VARCHAR2(30), balance_amount NUMBER(18,2));
INSERT INTO ACCOUNTS ('TOT',NULL,'Total');
INSERT INTO ACCOUNTS ('ANA1','TOT','General Expenses');
INSERT INTO ACCOUNTS ('4801001','ANA1','Small Expenses');
INSERT INTO ACCOUNTS ('4801002','ANA1','Transportation');
INSERT INTO ACCOUNTS ('ANA2','TOT','Health Expenses');
INSERT INTO ACCOUNTS ('4802001','ANA2','Healthcare');
INSERT INTO ACCOUNTS ('4802002','ANA2','Facilities');
INSERT INTO BALANCES ('4801001', 2000);
INSERT INTO BALANCES ('4801001', 1000);
INSERT INTO BALANCES ('4802001', 3000);
INSERT INTO BALANCES ('4802001', 4000);
Thanks for posting the CREATE TABLE and INSERT statements. Remember why you do it: so that the people who want to help you can re-create the problem and test their ideas. If the statments don't work, then they are not so useful. None of the INSERT statements you posted work: they all need a VALUES keyword. Please test those statments before you post them.
Also, make sure that the reuslts you post correspond to the sample data you post. In your sample data, there are no rows in balances for account_codes '4801002' or '4802002'.
I think you want something like this:
WITH connect_by_results AS
SELECT CONNECT_BY_ROOT account_code AS root_account_code
, account_code
FROM accounts
-- NOTE: No START WITH clause
CONNECT BY parent_account = PRIOR account_code
SELECT c.root_account_code || ' -> '
|| TO_CHAR (SUM (b.balance_amount)) AS txt
FROM connect_by_results c
LEFT OUTER JOIN balances b ON c.account_code = b.account_code
GROUP BY c.root_account_code
; -
Need to populate a hierarchical query results in detail block of WIPTXCFM
Hi All,
I would need to customize WIPTXCFM to populate all layered sub assembly schedule numbers against a Final Assembly schedule number.
Requirement is as soon as User enter a FA schedule number; it should populate all levels Sub Assembly Schedule Numbers under this.
I have thought of 1 approach; need suggestion if there is any better way to achieve this to improve the performance.
My Approach: In custom WIPTXCFM form once the FA schedule number is entered; I can fetch all below level data(e.g Level1, level2 ...etc.)
using a cursor with hierarchical query. Then loop through the cursor and insert them in the block after the FA record.
So would look for your suggestion if there is any other better way to achieve this.
Thanks in adv.
Regards.880860 wrote:
Hi All,
I would need to customize WIPTXCFM to populate all layered sub assembly schedule numbers against a Final Assembly schedule number.
Requirement is as soon as User enter a FA schedule number; it should populate all levels Sub Assembly Schedule Numbers under this.
I have thought of 1 approach; need suggestion if there is any better way to achieve this to improve the performance.
My Approach: In custom WIPTXCFM form once the FA schedule no is entered; I can fetch all below level data(e.g Level1, level2 ...etc.)
using a cursor with hierarchical query. Then loop through the cursor and insert them in the block after the FA record.
As per my findings; this hierarchical query takes longer to fetch the below levels data, around 1.5 mins.
Hello 880860,
If your are talking about EBS customization you can post at {forum:id=475}.
Hope this helps -
Problem with Hierarchical query
Gurus,
I have a problem with hierarchical query, which I am pasting below.
select sys_connect_by_path (Fname,'/')"PATH",Fname,id,level
,(SELECT COUNT(ID)-1 FROM (SELECT CONNECT_BY_ROOT LNAME LNAME,ID FROM CMT_PERSON
START WITH ID = 'emplo000000000126009'
CONNECT BY PRIOR ID=MANAGER_ID)
GROUP BY FNAME)"COUNT"
from CMT_PERSON
WHERE
LEVEL <= 4
----And ID='emplo000000000001877'
CONNECT BY PRIOR id=manager_id
----AND NOT LEVEL > 3
START WITH ID='emplo000000000126009'
As per the result, count is getting repeated for all the levels. That is, count is coming 16100 for every level, Can you please help where exactly I am going wrong
RegardsYou do not say anything about what count you want to get?
A wild guess could be:
select
sys_connect_by_path (p1.fname, '/') "PATH",
p1.fname,
p1.id,
level,
(select count (id) - 1
from
(select connect_by_root p2.lname lname, p2.id
from cmt_person p2
start with p2.id = p1.id
connect by prior p2.id = p2.manager_id)
) "COUNT"
from cmt_person p1
where level <= 4
connect by prior p1.id = p1.manager_id
start with p1.id = 'emplo000000000126009';Since your inner query simply starts with the hardcoded employee id, naturally it will give you the same count.
My guess is your inner query should start with the person id from the outer query?
If that is not the case - please state in plain english what you are trying to accomplish ;-)
(Oh, and please paste code within tags so we can read it more easily...) -
Hierarchical Query for Chart of Account
Hellow all
I have one Table which is for chart of account
The Column in this Table is
Acc_id and Acc_name
I Insert data in This chart of account
Insert into COA
values
*(01,'ASSETS');*
values
*(01001,'Current Assets');*
values
*(01002,'Fixed Assets');*
values
*(010010001,'Banks');*
values
*(010010002,'Cash');*
values
*(01001000100001,'Metrol Politan Bank');*
values
*(01001000100002,'Royal Bank');*
values
*(01001000100003,'Stander Charted Bank');*
values
*(01001000200001,'Cash in Hand');*
values
*(01001000200002,'Patty Cash');*
That's all my record now i need to create a Hierarchical tree
Which look like this
*01- Assets*
------010001 Current Assets+
----------010010001 Bank+
--------------01001000100001 Metrol Politan Bank+
--------------01001000100002 Royal Bank+
--------------01001000100003 Stander Charted Bank+
----------010010002 Cash+
--------------01001000200001 Cash in Hand+
--------------01001000200002 Patty Cash+
------010002 Fixed Assets+
----------010020001 Machinery Assets+
--------------01002000100001 Needle Machine+
--------------01002000100002 GGT Machine+
----------010020002 Computer Assets+
--------------01002000200001 Computer Server+
--------------01002000200002 Computer other+
Hope you guys understand i need the Hierarchical query for making this kind of Tree
Regards
ShahzaibIn above posts you have solution to your problem but maybe you can think about changeing the design slightly.
I would suggest using parent_id to find parent account, instead of operations on strings which can be slower in larger tables.
SQL> create table t14(id int, account_code varchar2(16), account_name varchar2(32), parent_id int)
2 /
Table created.
SQL> insert into t14 values(1,'01','Assets',null);
1 row created.
SQL> insert into t14 values(2,'01001','Current Assets',1);
1 row created.
SQL> insert into t14 values(3,'01002','Current Assets',1);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t14;
ID ACCOUNT_CODE ACCOUNT_NAME PARENT_ID
1 01 Assets
2 01001 Current Assets 1
3 01002 Current Assets 1
SQL> select lpad(' ',2*(level-1)) || account_code as account_code, account_name
2 from t14
3 start with parent_id is null connect by prior id = parent_id
4 /
ACCOUNT_CODE ACCOUNT_NAME
01 Assets
01001 Current Assets
01002 Current AssetsWith kind regards
Krystian Zieja -
Hierarchical query with where clause
Hi,
How can I query hierarchically a query with WHERE clause? I have a table with three fields session_id,id and root_id.
When I try with the following query,
select id, level from relation
where session_id = 79977
connect by prior id = root_id start with id = 5042;
It gets duplicate values.
I want the query to show in the hierarchical manner with a filter condition using WHERE clause. Please help me how can I achieve this. If you know any link that describes more about this, please send it.
Thanks in Advance.
Regards,
-ParmyHi Sridhar Murthy an others,
Thanks a lot for your/the answer. It's working for me. It saved a lot of other work around without the proper knowledge of hierarchical query. Please send me any link that describes these issues in detail and also I hope as I have mentioned in the other message, same cannot be achieved on views or ( on two different tables ???)
Any way thanks for your reply,
It's working for me.
With happiness,
-Parmy -
Problem with different execution paths in hierarchical query
Hello,
I have problems with the following query:
SELECT DISTINCT P.ID FROM PRODUCTELEMENTIMPL P WHERE ( ( LABEL = 'SomeLabel' AND PRODUCTELEMENTTYPE = 'SomeText' AND ( STATE = 'created' OR STATE = 'stored' OR STATE = 'archived' OR STATE = 'archivedRestored' ) ) ) START WITH P.ID = 42 CONNECT BY PRIOR P.ID = P.PARENT
We have two databases (an Oracle 10g XE and Oracle10g Enterprise). In the XE Database the query is executed very fast, but in the main installation it takes minutes. If I "explain" the query I get two different execution paths:
The fast:
ID PARENT_ID LEVEL SQL Kosten Anzahl Zeilen
0 - 1 SELECT STATEMENT 20 49
1 0 2 HASH UNIQUE 20 49
2 1 3 FILTER - -
3 2 4 CONNECT BY WITH FILTERING - -
4 3 5 TABLE ACCESS BY INDEX ROWID PRODUCTELEMENTIMPL (TABLE) - -
5 4 6 INDEX UNIQUE SCAN SYS_C0072201 (INDEX (UNIQUE)) 2 1
6 3 5 NESTED LOOPS - -
7 6 6 BUFFER SORT - -
8 7 7 CONNECT BY PUMP - -
9 6 6 TABLE ACCESS BY INDEX ROWID PRODUCTELEMENTIMPL (TABLE) 19 49
10 9 7 INDEX RANGE SCAN PRODUCTELEMENTIMPL_IDX1 (INDEX) 3 49
11 3 5 TABLE ACCESS FULL PRODUCTELEMENTIMPL (TABLE) 19 49
Slow:
ID PARENT_ID LEVEL SQL Kosten Anzahl Zeilen
0 1 SELECT STATEMENT 1 1
1 0 2 HASH UNIQUE 1 1
2 1 3 FILTER
3 2 4 CONNECT BY WITHOUT FILTERING
4 3 5 TABLE ACCESS BY INDEX ROW 3 1
ID PRODUCTELEMENTIMPL (TABLE)
5 4 6 INDEX UNIQUE SCAN SYS_C0 2 1
020528 (INDEX (UNIQUE))
6 3 5 TABLE ACCESS FULL PRODUCT 6628 1100613
ELEMENTIMPL (TABLE)
Any ideas how to avoid this full table scan?
bye
Roland SpatzeneggerHello,
thank you for your replies. The indices and table schemas are the "same", but only the content for the tables was mirrored.
We made some tests with dropping and/or analyzing the tables, but it didn't change anything.
The main problem is that the query takes 33s in the productive environment for searching in a couple of rows. At the moment it's faster to make
SELECT DISTINCT P.ID, P.STATE FROM PRODUCTELEMENTIMPL P WHERE ( ( LABEL = 'SomeLabel' AND PRODUCTELEMENTTYPE = 'SomeText' ) ) START WITH P.ID = 42 CONNECT BY PRIOR P.ID = P.PARENT
and to test in the application if the state-values match ;-)
If I add the hint /*+ no_filtering */ in the test environment, I get the same "slow" execution path as in the production environment. So the question is, what prevents the filtering in "connect by"?
(I think in the fast version it filters only the results of the hierarchical query, in the slow version it first filters the whole table and joins/merge it with the hierachical result).
bye
Roland Spatzenegger
Maybe you are looking for
-
Headphone output not working on Audigy 2 ZS Platinum Pro
I've installed the (only available) beta driver for Vista under Vista RTM, but can't get the headphone output to work at all... Sound keeps playing through the line out, but no matter what i do i can't get it routed through the headphone output. Is i
-
Will Acrobat Pro 9 be compatible with OS X 10.7 Lion?
Will Acrobat Pro 9 be be compatible with OS X 10.7 Lion?
-
Pb avec facetime sur mon mac (suis pas visible mais audible)
Bonjour, j'ai un problème. Lorsque j'utilise facetime avec mon mac, les gens m'entendent mais ne me voient pas. Moi je les entends et les vois parfaitement. J'ai pensé que c'était peut être lié à ma connexion wifi chez moi mais lorsque sur le même ré
-
Not able to use internet sharing on my iMac 8.1 using Mac OS X 10.6.8
Im not able to use internet sharing on my iMac 8.1 using Mac OS X 10.6.8, I tried internet sharing with OS Lion and it works fine. Has anybody else experience this problem and what was the solutions.
-
SXMB_MONI - Message Status - Automatic Restart
Hello, When a message in transferred, in transaction SXMB the message has an "AUTOMATIC RESTART" icon. Other messages stuck in the queue and are waiting for the message to restart. Only after some time, the "AUTOMATIC RESTART" icon converts to "Red F