Sys_connect_by_path
Hi All,
I have table X which has two columns.
Data is following
Id Desc
1 My Test
1 My Test1
1 My Test2
2 My Test
2 My Test
I need output as shown below a Pivot.
Id Desc
1 My Test - My Test1 - My Test2
2 My Test - My Test
Number of rows can be dynamic for a given id.
I want to achive through SQL without writing an ORACLE function or procedure. Is there any way we can achive this?
Please help me out.
Thanks in Advance.
GVR.
like this or another way??
with tab_1 as(select 1 sid, 'My Test' sname from dual union all
select 1, 'My Test1' from dual union all
select 1, 'My Test2' from dual union all
select 2, 'My Test' from dual union all
select 2, 'My Test' from dual)
SELECT sid,
LTRIM(MAX(SYS_CONNECT_BY_PATH(sname,'-'))
KEEP (DENSE_RANK LAST ORDER BY curr),'-') AS employees
FROM (SELECT sid, sname,
ROW_NUMBER() OVER (PARTITION BY sid ORDER BY sname) AS curr,
ROW_NUMBER() OVER (PARTITION BY sid ORDER BY sname) -1 AS prev
FROM tab_1)
GROUP BY sid
CONNECT BY prev = PRIOR curr AND sid = PRIOR sid START WITH curr = 1;
or
with tab_1 as(select 1 sid, 'My Test' sname from dual union all
select 1, 'My Test1' from dual union all
select 1, 'My Test2' from dual union all
select 2, 'My Test' from dual union all
select 2, 'My Test' from dual)
SELECT sid,
LTRIM(MAX(SYS_CONNECT_BY_PATH(sname,'-'))
KEEP (DENSE_RANK LAST ORDER BY curr),'-') AS employees
FROM (SELECT sid, sname,
ROW_NUMBER() OVER (PARTITION BY sid ORDER BY sname) AS curr
FROM tab_1)
GROUP BY sid
CONNECT BY curr-1 = PRIOR curr AND sid = PRIOR sid START WITH curr = 1;
Similar Messages
-
How to pass 2nd argument as parameter to SYS_CONNECT_BY_PATH in PLSQL
Hi All,
I've the following tables and data:
CREATE TABLE seg_tab (seg_no NUMBER, seg_value VARCHAR2(10));
--1st Subset
INSERT INTO seg_tab VALUES (1,'01');
--2nd Subset
INSERT INTO seg_tab VALUES (2,'001');
INSERT INTO seg_tab VALUES (2,'002');
--3rd Subset
INSERT INTO seg_tab VALUES (3,'100040');
INSERT INTO seg_tab VALUES (3,'100041');
INSERT INTO seg_tab VALUES (3,'100042');
INSERT INTO seg_tab VALUES (3,'100043');
I'm trying to write PLSQL function to generate combination of seg_values using the following code:
DECLARE l_separator VARCHAR2(10):='.'; BEGIN FOR i IN ( SELECT SUBSTR ( SYS_CONNECT_BY_PATH (seg_value, l_separator), 2) AS codes FROM seg_tab WHERE CONNECT_BY_ISLEAF = 1 START WITH seg_no = 1 CONNECT BY seg_no = PRIOR seg_no + 1) LOOP DBMS_OUTPUT.PUT_LINE(i.seg_path); END; /
When i'm trying to run this code, it is generating the error "Invalid argument to SYS_CONNECT_BY_PATH". When I change the second argument to static value such as '.', it is working fine. The reason I need it that we are using dynamic separator character and is something compulsory.
Can anyone please help me to rectify it.
Many Thanks
Kind Regards,
BilalOr use a static separator, and replace that separator in the generated path dynamicly.
Something like:
replace( substr( sys_connect_by_path( seg_value, '~' ), 2 ), '~', l_separator )
You just have to use a static value which doesn't occur in your data, seg_value in this case. -
Hierarchical sys_connect_by_path query needing to process child results
Application Express 4.0.2.00.06 - DB 10.2
Hello all!
I work for an organization having rooms, each with a defined relationship to some or all of the other rooms (some higher, some lower) which must be observed by personnel moving between them.
I've been tasked with writing an page(extending an existing app in which the relationships are managed) in which if a user provide a list of rooms they wish to visit, a list of hierarchy options will be provided based on the relationship rules between rooms.
It is implied that given a sourcename/destname pair, sourcename can go to destname and the inverse is also true (destname can come/receive from sourcename)
This is my sample data set (heavily filtered from actual data);
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME
28 Ax1 76 G3A
28 Ax1 27 FGB44
58 MP23 27 FGB44
58 MP23 104 MP22
58 MP23 76 G3A
76 G3A 27 FGB44
104 MP22 76 G3A
104 MP22 58 MP23Using this query, I'm able to build the beginning of my hierarchy.
SELECT DISTINCT source_roomid,
sourcename,
dest_roomid,
destname,
sourcename|| ',' ||REVERSE(sys_connect_by_path(REVERSE(destname),',')) path,
(REVERSE(sys_connect_by_path(REVERSE(sourcename),',')))parents,
(REVERSE(sys_connect_by_path(REVERSE(destname),',')))children
FROM (SELECT source_roomid, A.NAME AS sourcename, dest_roomid, b.NAME AS destname
FROM rm_approved_room_state, rm_room A, rm_room b
WHERE source_roomid IN (27, 28, 58, 76, 104)
AND dest_roomid IN (27, 28, 58, 76, 104)
AND a.roomid = source_roomid
AND b.roomid = dest_roomid)
--START WITH source_roomid IN (27, 28, 58, 76, 104)
CONNECT BY NOCYCLE PRIOR source_roomid = dest_roomid
order by 1And my initial result set is:
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
28 Ax1 27 FGB44 Ax1,FGB44, Ax1, FGB44,
28 Ax1 76 G3A Ax1,G3A, Ax1, G3A,
28 Ax1 76 G3A Ax1,G3A,FGB44, Ax1,G3A, G3A,FGB44,
58 MP23 27 FGB44 MP23,FGB44, MP23, FGB44,
58 MP23 76 G3A MP23,G3A, MP23, G3A,
58 MP23 76 G3A MP23,G3A,FGB44, MP23,G3A, G3A,FGB44,
58 MP23 104 MP22 MP23,MP22, MP23, MP22,
58 MP23 104 MP22 MP23,MP22,G3A, MP23,MP22, MP22,G3A,
58 MP23 104 MP22 MP23,MP22,G3A,FGB44, MP23,MP22,G3A, MP22,G3A,FGB44,
58 MP23 104 MP22 MP23,MP22,MP23, MP23,MP22, MP22,MP23,
76 G3A 27 FGB44 G3A,FGB44, G3A, FGB44,
104 MP22 58 MP23 MP22,MP23, MP22, MP23,
104 MP22 58 MP23 MP22,MP23,FGB44, MP22,MP23, MP23,FGB44,
104 MP22 58 MP23 MP22,MP23,G3A, MP22,MP23, MP23,G3A,
104 MP22 58 MP23 MP22,MP23,G3A,FGB44, MP22,MP23,G3A, MP23,G3A,FGB44,
104 MP22 58 MP23 MP22,MP23,MP22, MP22,MP23, MP23,MP22,
104 MP22 76 G3A MP22,G3A, MP22, G3A,
104 MP22 76 G3A MP22,G3A,FGB44, MP22,G3A, G3A,FGB44,The challenge for me is that for the hierarchy to be correct, every hierarchy row where level >= 2 needs a check to determine if the latest child can receive from the previous child otherwise filter those lines out. Also, paths where there is duplicated data needs to be removed leaving the longest heirarchy intact.
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
28 Ax1 27 FGB44 Ax1,FGB44, Ax1, FGB44,
(****THE NEXT LINE IS NOT NECESSARY BECAUSE THE NEXT LINE ALREADY CONTAINS THIS HIERARCHY DATA****)
28 Ax1 76 G3A Ax1,G3A, Ax1, G3A,
28 Ax1 76 G3A Ax1,G3A,FGB44, Ax1,G3A, G3A,FGB44,I also need to pull out instances of where rooms related to each other as in this case.
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
104 MP22 58 MP23 MP22,MP23,MP22, MP22,MP23, MP23,MP22,Leaving this as the anticipated output.
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
28 Ax1 27 FGB44 Ax1,FGB44, Ax1, FGB44,
28 Ax1 76 G3A Ax1,G3A,FGB44, Ax1,G3A, G3A,FGB44,
58 MP23 27 FGB44 MP23,FGB44, MP23, FGB44,
58 MP23 76 G3A MP23,G3A,FGB44, MP23,G3A, G3A,FGB44,
58 MP23 104 MP22 MP23,MP22,G3A, MP23,MP22, MP22,G3A,
76 G3A 27 FGB44 G3A,FGB44, G3A, FGB44,
104 MP22 58 MP23 MP22,MP23,G3A, MP22,MP23, MP23,G3A,
104 MP22 76 G3A MP22,G3A, MP22, G3A,Any thoughts on how I might get these last three things done in my hierarchy example?
Many thanks in advance!
Paul
Edited by: pgtaviator on Nov 9, 2011 4:34 PMHi, Paul,
Sorry, it's unclear what you want.
pgtaviator wrote:
Application Express 4.0.2.00.06 - DB 10.2
Hello all!
I work for an organization having rooms, each with a defined relationship to some or all of the other rooms (some higher, some lower) which must be observed by personnel moving between them.
I've been tasked with writing an page(extending an existing app in which the relationships are managed) in which if a user provide a list of rooms they wish to visit, a list of hierarchy options will be provided based on the relationship rules between rooms.
It is implied that given a sourcename/destname pair, sourcename can go to destname and the inverse is also true (destname can come/receive from sourcename)If "the inverse is also true", why don't the desired results include any paths such as
G3A,Ax1 or
FGB44,MP23,MP22 ?
This is my sample data set (heavily filtered from actual data);
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME
28 Ax1 76 G3A
28 Ax1 27 FGB44
58 MP23 27 FGB44
58 MP23 104 MP22
58 MP23 76 G3A
76 G3A 27 FGB44
104 MP22 76 G3A
104 MP22 58 MP23
Please post CREATE TABLE and INSERT statements for the sample data.
Is this de-normalized data? That is, does roomid=28 always correspond to name='Ax1', and name='Ax1' always correspond to roomid=28? If not, include examples in your sample data and results, and explain.
Using this query, I'm able to build the beginning of my hierarchy.
SELECT DISTINCT source_roomid,
sourcename,
dest_roomid,
destname,
sourcename|| ',' ||REVERSE(sys_connect_by_path(REVERSE(destname),',')) path,
(REVERSE(sys_connect_by_path(REVERSE(sourcename),',')))parents,
(REVERSE(sys_connect_by_path(REVERSE(destname),',')))children
FROM (SELECT source_roomid, A.NAME AS sourcename, dest_roomid, b.NAME AS destname
FROM rm_approved_room_state, rm_room A, rm_room b
WHERE source_roomid IN (27, 28, 58, 76, 104)
AND dest_roomid IN (27, 28, 58, 76, 104)
AND a.roomid = source_roomid
AND b.roomid = dest_roomid)
--START WITH source_roomid IN (27, 28, 58, 76, 104)
CONNECT BY NOCYCLE PRIOR source_roomid = dest_roomid
order by 1
Thanks for posting the existing query; that's very helpful.
REVERSE is not a documented Oracle function. Using undocumneted functions isn't a very good idea. In this case, can't you just change the CONNECT BY clause to:
CONNECT BY NOCYCLE source_roomid = PRIOR dest_roomidto get the results you want?
And my initial result set is:
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
28 Ax1 27 FGB44 Ax1,FGB44, Ax1, FGB44,
28 Ax1 76 G3A Ax1,G3A, Ax1, G3A,
28 Ax1 76 G3A Ax1,G3A,FGB44, Ax1,G3A, G3A,FGB44,
58 MP23 27 FGB44 MP23,FGB44, MP23, FGB44,
58 MP23 76 G3A MP23,G3A, MP23, G3A,
58 MP23 76 G3A MP23,G3A,FGB44, MP23,G3A, G3A,FGB44,
58 MP23 104 MP22 MP23,MP22, MP23, MP22,
58 MP23 104 MP22 MP23,MP22,G3A, MP23,MP22, MP22,G3A,
58 MP23 104 MP22 MP23,MP22,G3A,FGB44, MP23,MP22,G3A, MP22,G3A,FGB44,
58 MP23 104 MP22 MP23,MP22,MP23, MP23,MP22, MP22,MP23,
76 G3A 27 FGB44 G3A,FGB44, G3A, FGB44,
104 MP22 58 MP23 MP22,MP23, MP22, MP23,
104 MP22 58 MP23 MP22,MP23,FGB44, MP22,MP23, MP23,FGB44,
104 MP22 58 MP23 MP22,MP23,G3A, MP22,MP23, MP23,G3A,
104 MP22 58 MP23 MP22,MP23,G3A,FGB44, MP22,MP23,G3A, MP23,G3A,FGB44,
104 MP22 58 MP23 MP22,MP23,MP22, MP22,MP23, MP23,MP22,
104 MP22 76 G3A MP22,G3A, MP22, G3A,
104 MP22 76 G3A MP22,G3A,FGB44, MP22,G3A, G3A,FGB44,The challenge for me is that for the hierarchy to be correct, every hierarchy row where level >= 2 needs a check to determine if the latest child can receive from the previous child otherwise filter those lines out.I don't understand the requirement above at all.
Also, paths where there is duplicated data needs to be removed leaving the longest heirarchy intact.
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
28 Ax1 27 FGB44 Ax1,FGB44, Ax1, FGB44,
(****THE NEXT LINE IS NOT NECESSARY BECAUSE THE NEXT LINE ALREADY CONTAINS THIS HIERARCHY DATA****)
28 Ax1 76 G3A Ax1,G3A, Ax1, G3A,
28 Ax1 76 G3A Ax1,G3A,FGB44, Ax1,G3A, G3A,FGB44,
Are you using "THE NEXT LINE" to mean 2 different things? Do you mean "The line with Ax1,G3A is not wanted because it is a sub-path of Ax1,G3A,FGB44"?
Why do the desired results include
MP22,G3A (which is a sub-path of MP23.MP22,G3A) and
G3A,FGB44 (which is a sub-path of both Ax1,G3A,FGB44 and MP23,G3A,FGB44)?
I also need to pull out instances of where rooms related to each other as in this case.
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
104 MP22 58 MP23 MP22,MP23,MP22, MP22,MP23, MP23,MP22,
When you way "rooms related to each other", do you mean "rooms related to themselves"? It looks like you're saying that no room can occur 2 (or more) times in any path.
Leaving this as the anticipated output.
SOURCE_ROOMID SOURCENAME DEST_ROOMID DESTNAME PATH PARENTS CHILDREN
28 Ax1 27 FGB44 Ax1,FGB44, Ax1, FGB44,
28 Ax1 76 G3A Ax1,G3A,FGB44, Ax1,G3A, G3A,FGB44,
58 MP23 27 FGB44 MP23,FGB44, MP23, FGB44,
58 MP23 76 G3A MP23,G3A,FGB44, MP23,G3A, G3A,FGB44,
58 MP23 104 MP22 MP23,MP22,G3A, MP23,MP22, MP22,G3A,
76 G3A 27 FGB44 G3A,FGB44, G3A, FGB44,
104 MP22 58 MP23 MP22,MP23,G3A, MP22,MP23, MP23,G3A,
104 MP22 76 G3A MP22,G3A, MP22, G3A,
Why do 3 of the paths end at G3A? Why don't they continue to FGB44 as 2 of the paths do?
Why is MP23,G3A,FGB44 in the desired output, and not MP22,MP23,G3A,FGB44 (which is longer)?
Why isn't MP22,MP23,FGB44 in the desired results, but its sub-path MP23,FGB44 is?
Try describing what you're trying to show in this query, and what each row of the desired result set represents. As far as possible, avoid repeating the explanation you're already used. (Not that there's anything wrong with what you've said so far; it's just that I need all the help I can get to understand the probhlem.)
Any thoughts on how I might get these last three things done in my hierarchy example?It looks like CONNECT_BY_ISLEAF, and maybe CONNECT_BY_ISCYCLE could help in this problem.
Regular expressions, or perhaps LIKE, might help in detecting if one path contains another.
Many thanks in advance!
Paul
Edited by: pgtaviator on Nov 9, 2011 4:34 PM -
ORA-01489 sys_connect_by_path and previous solution not working
Hi all.
Oracle version:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
"CORE 11.2.0.1.0 Production"
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
I need to get routes in a map and the associated sum of distances from some point to another.
map
-- 9
F ----------E
| \ |
| \2 |6
| \ 11 |
14| C-------D
| / \10 /
| /9 \ /15
|/ \ /
A-------B
7I have a query that correctly gets the routes.
WITH distances AS
SELECT 'A' n1, 'B' n2, 7 d FROM DUAL UNION
SELECT 'A' n1, 'C' n2, 9 d FROM DUAL UNION
SELECT 'A' n1, 'F' n2, 14 d FROM DUAL UNION
SELECT 'B' n1, 'D' n2, 15 d FROM DUAL UNION
SELECT 'B' n1, 'C' n2, 10 d FROM DUAL UNION
SELECT 'C' n1, 'D' n2, 11 d FROM DUAL UNION
SELECT 'C' n1, 'F' n2, 2 d FROM DUAL UNION
SELECT 'D' n1, 'E' n2, 6 d FROM DUAL UNION
SELECT 'F' n1, 'E' n2, 9 d FROM DUAL
SELECT
'A'||sys_connect_by_path(n2,'-') path,
SUBSTR(sys_connect_by_path(d,'+'),2) sum_dist
FROM distances
START WITH n1='A'
CONNECT BY NOCYCLE PRIOR n2=n1;
A-B 7
A-B-C 7+10
A-B-C-D 7+10+11
A-B-C-D-E 7+10+11+6
A-B-C-F 7+10+2
A-B-C-F-E 7+10+2+9
A-B-D 7+15
A-B-D-E 7+15+6
A-C 9
A-C-D 9+11
A-C-D-E 9+11+6
A-C-F 9+2
A-C-F-E 9+2+9
A-F 14
A-F-E 14+9The problem is when there are a lot of nodes, I get an ORA-01489: result of string concatenation is too long.
I followed this link.
sys_connect_by_path & to_CLOB
I built the specified package but apparently is combining elements.
If it's called just one time.
WITH distances AS
SELECT 'A' n1, 'B' n2, 7 d FROM DUAL UNION
SELECT 'A' n1, 'C' n2, 9 d FROM DUAL UNION
SELECT 'A' n1, 'F' n2, 14 d FROM DUAL UNION
SELECT 'B' n1, 'D' n2, 15 d FROM DUAL UNION
SELECT 'B' n1, 'C' n2, 10 d FROM DUAL UNION
SELECT 'C' n1, 'D' n2, 11 d FROM DUAL UNION
SELECT 'C' n1, 'F' n2, 2 d FROM DUAL UNION
SELECT 'D' n1, 'E' n2, 6 d FROM DUAL UNION
SELECT 'F' n1, 'E' n2, 9 d FROM DUAL
SELECT
'A'||'-'||hierarchy.branch(LEVEL,n2,'-') path
FROM distances
START WITH n1='A'
CONNECT BY NOCYCLE PRIOR n2=n1;
A-B
A-B-C
A-B-C-D
A-B-C-D-E
A-B-C-F
A-B-C-F-E
A-B-D
A-B-D-E
A-C
A-C-D
A-C-D-E
A-C-F
A-C-F-E
A-FBut if I call it twice in the same query...
WITH distances AS
SELECT 'A' n1, 'B' n2, 7 d FROM DUAL UNION
SELECT 'A' n1, 'C' n2, 9 d FROM DUAL UNION
SELECT 'A' n1, 'F' n2, 14 d FROM DUAL UNION
SELECT 'B' n1, 'D' n2, 15 d FROM DUAL UNION
SELECT 'B' n1, 'C' n2, 10 d FROM DUAL UNION
SELECT 'C' n1, 'D' n2, 11 d FROM DUAL UNION
SELECT 'C' n1, 'F' n2, 2 d FROM DUAL UNION
SELECT 'D' n1, 'E' n2, 6 d FROM DUAL UNION
SELECT 'F' n1, 'E' n2, 9 d FROM DUAL
SELECT
'A'||SUBSTR(hierarchy.branch(LEVEL,n2,'-'),2) path,
hierarchy.branch(LEVEL,d,'+') sum_dist
FROM distances
START WITH n1='A'
CONNECT BY NOCYCLE PRIOR n2=n1;
A 7
A-C 7+10
A-10-D 7+10+11
A-10-11-E 7+10+11+6
A-10-F 7+10+2
A-10-2-E 7+10+2+9
A-D 7+15
A-15-E 7+15+6
A 9
A-D 9+11
A-11-E 9+11+6
A-F 9+2
A-2-E 9+2+9As you can see, is combining the elements (A-10-11-E) node - distance - distance - node
Do I have to create separate functions in the package, one per column?, or is there another way to solve this problem?, or even better, another way to solve the original problem (ORA-01489)
Thanks a lot.
Regards.
Package code (by Solomon Yakobson):
CREATE OR REPLACE
PACKAGE Hierarchy
IS
TYPE BranchTableVarchar2Type IS TABLE OF VARCHAR2(4000)
INDEX BY BINARY_INTEGER;
BranchTableVarchar2 BranchTableVarchar2Type;
TYPE BranchTableClobType IS TABLE OF CLOB
INDEX BY BINARY_INTEGER;
BranchTableClob BranchTableClobType;
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN VARCHAR2,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0)
RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES(Branch,WNDS);
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN CLOB,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0)
RETURN CLOB;
PRAGMA RESTRICT_REFERENCES(Branch,WNDS);
END Hierarchy;
CREATE OR REPLACE
PACKAGE BODY Hierarchy
IS
ReturnValueVarchar2 VARCHAR2(4000);
ReturnValueClob CLOB;
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN VARCHAR2,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0)
RETURN VARCHAR2
IS
BEGIN
BranchTableVarchar2(p_Level) := p_Value;
ReturnValueVarchar2 := p_Value;
FOR I IN REVERSE 1..p_Level - 1 LOOP
ReturnValueVarchar2 := BranchTableVarchar2(I)|| p_Delimiter || ReturnValueVarchar2;
END LOOP;
RETURN ReturnValueVarchar2;
END Branch;
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN CLOB,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0)
RETURN CLOB
IS
BEGIN
BranchTableClob(p_Level) := p_Value;
ReturnValueClob := p_Value;
FOR I IN REVERSE 1..p_Level - 1 LOOP
ReturnValueClob := BranchTableClob(I)|| p_Delimiter || ReturnValueClob;
END LOOP;
RETURN ReturnValueClob;
END Branch;
END Hierarchy;
/Edited by: sKr on 08-mar-2012 17:29
Package code addedHi,
sKr wrote:
Hi all.
Oracle version:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
"CORE 11.2.0.1.0 Production"
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
I need to get routes in a map and the associated sum of distances from some point to another.
map
-- 9
F ----------E
| \ |
| \2 |6
| \ 11 |
14| C-------D
| / \10 /
| /9 \ /15
|/ \ /
A-------B
7... I wish we could mark questions as "Helpful" or "Correct". You'd get 10 points for sure.
Do I have to create separate functions in the package, one per column?,You don't need separate functions. One user-defined function should be enough, just like one built-in version of SYS_CONNECT_BY_PATH is enough. Whatever it has to store internally, it knows to keep a separate copy for every argument that you call it with. The problem with the package, as originally posted, is that there's only one internal variable BranchTableVarchar2. Instead of one variable, make an array of similar variables, and add an optional argument to the branch funtion to tell it which element in that array to use.
CREATE OR REPLACE
PACKAGE Hierarchy
IS
TYPE BranchTableVarchar2Type IS TABLE OF VARCHAR2(4000)
INDEX BY BINARY_INTEGER;
BranchTableVarchar2 BranchTableVarchar2Type;
TYPE VList IS TABLE OF BranchTableVarchar2Type -- *** NEW ***
INDEX BY BINARY_INTEGER; -- *** NEW ***
vl VList; -- *** NEW ***
TYPE BranchTableClobType IS TABLE OF CLOB
INDEX BY BINARY_INTEGER;
BranchTableClob BranchTableClobType;
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN VARCHAR2,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0),
p_PathNum IN PLS_INTEGER DEFAULT 1 -- *** NEW ***
RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES(Branch,WNDS);
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN CLOB,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0)
RETURN CLOB;
PRAGMA RESTRICT_REFERENCES(Branch,WNDS);
END Hierarchy;
SHOW ERRORS
PROMPT ========== FK BODY ==========
CREATE OR REPLACE
PACKAGE BODY Hierarchy
IS
ReturnValueVarchar2 VARCHAR2(4000);
ReturnValueClob CLOB;
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN VARCHAR2,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0),
p_PathNum IN PLS_INTEGER DEFAULT 1 -- *** NEW ***
RETURN VARCHAR2
IS
BEGIN
vl (p_PathNum) (p_Level) := p_Value; -- *** CHANGED ***
ReturnValueVarchar2 := p_Value;
FOR I IN REVERSE 1..p_Level - 1 LOOP
ReturnValueVarchar2 := vl (p_PathNum) (I) -- *** CHANGED ***
|| p_Delimiter
|| ReturnValueVarchar2;
END LOOP;
RETURN ReturnValueVarchar2;
END Branch;
FUNCTION Branch(
p_Level IN NUMBER,
p_Value IN CLOB,
p_Delimiter IN VARCHAR2 DEFAULT CHR(0)
RETURN CLOB
IS
BEGIN
BranchTableClob(p_Level) := p_Value;
ReturnValueClob := p_Value;
FOR I IN REVERSE 1..p_Level - 1 LOOP
ReturnValueClob := BranchTableClob(I)|| p_Delimiter || ReturnValueClob;
END LOOP;
RETURN ReturnValueClob;
END Branch;
END Hierarchy;
SHOW ERRORSAs you can see, I only changed the VARCHAR2 version. I'll leave changing the CLOB version as an exercise for you.
When you call branch, pass a unique number for each column of output. If you don't explicitly give a number, it will default to 0.
Here's your query modified to call it:
SELECT 'A' || SUBSTR ( hierarchy.branch ( LEVEL
, n2
, 2
) AS path
, hierarchy.branch ( LEVEL
, d
, '+'
, 12
) AS sum_dist
FROM distances
START WITH n1 = 'A'
CONNECT BY NOCYCLE PRIOR n2 = n1
;For path, I called branch with only 3 arguments, so it's using vl (0) for internal storage for path.
For sum_dist, I had to use a different integer. I couldn't decide if I should use 1 or 2, so I compromised and used 12. I could have used any integer, except 0.
Output:
PATH SUM_DIST
A 7
A-C 7+10
A-C-D 7+10+11
A-C-D-E 7+10+11+6
A-C-F 7+10+2
A-C-F-E 7+10+2+9
A-D 7+15
A-D-E 7+15+6
A 9
A-D 9+11
A-D-E 9+11+6
A-F 9+2
A-F-E 9+2+9
A 14
A-E 14+9
or is there another way to solve this problem?, or even better, another way to solve the original problem (ORA-01489)Since you're calling a user-defined package, you might want to add other features to the package.
For starters, in addition to a function that returns a string like '7+10+11', it might be handy to have a string that keeps those numbers internally, but returns the actual value 7 + 10 + 11 = 28.
If you're using this for problems where you want to find the path with the least total d (or the greatest total d, for that matter, but for now let's say you're only interested in the minimum), you might want a function that keeps track of the minimum total d encountered so far for each node. Every time you find a different path to a node, the function could check to see if the total d is better than the previous best. If not, it could return a flag (sort of like CONNECT_BY_ISCYCLE) that tells you not to bother with that path any more. -
Issue with sys_connect_by_path
Hi all,
Let me preface this post with I'm new to Oracle, using 10g, and mostly a self taught SQL person so it's not my strong suit. The overall goal is I'm trying to find folders within an area of our document management system that haven't been touched so we can perform some clean up. What I have to do is first find all active documents and its' parent folder in the hierarchy then compare the active folders to all folders to get my inactive folders. I have the first part of this working with the following:
SELECT Distinct(ActiveFolderID)
FROM (SELECT DataID, substr(sys_connect_by_path(DataID, '\'), instr(sys_connect_by_path(DataID, '\'),
'\', 1,2) + 1, instr(sys_connect_by_path(DataID, '\'), '\',1,3)
- instr(sys_connect_by_path(DataID, '\'), '\',1,2)-1) ActiveFolderID
FROM DTree
START WITH DataID = 9081729
CONNECT BY PRIOR DataID = ParentID) dt, DAuditNew da
WHERE dt.DataID=da.DataID AND DA.PERFORMERID != 11681125 AND da.AuditDate > SysDate - 90Where I run into an issue is when I add the next part to select folders that aren't in the above result:
SELECT DataID, Name
FROM DTree
WHERE SubType=0 AND ParentID=9081729 AND DataID NOT IN (SELECT Distinct(ActiveFolderID)
FROM (SELECT DataID, substr(sys_connect_by_path(DataID, '\'), instr(sys_connect_by_path(DataID, '\'),
'\', 1,2) + 1, instr(sys_connect_by_path(DataID, '\'), '\',1,3)
- instr(sys_connect_by_path(DataID, '\'), '\',1,2)-1) ActiveFolderID
FROM DTree
START WITH DataID = 9081729
CONNECT BY PRIOR DataID = ParentID) dt, DAuditNew da
WHERE dt.DataID=da.DataID AND DA.PERFORMERID != 11681125 AND da.AuditDate > SysDate - 90)I get the following error:
ORA-30004: when using SYS_CONNECT_BY_PATH function, cannot have seperator as part of column value
30004. 00000 - "when using SYS_CONNECT_BY_PATH function, cannot have seperator as part of column value"
*Cause:
*Action: Use another seperator which does not occur in any column value,
then retry.
I know there are no \ in DataID as it a numeric field, but I have tried other seperators with no luck. Any ideas? Hopefully it's not something simple that I screwed up.
Thanks,
BryanHi, Byran,
One way to get the results you want would be a MINUS operation. If I understand the requirements, you want
(a) the set of all folders that are one level down from any node called 'root'
MINUS
(b) the subset of folders in (a) that have descendants whose names start with 'Activefile' and were audited no more than 90 days ago.
We can get (a) with a self-join.
We can get (b) with CONNECT BY, using (a) in the START WITH clause. In Oracle 9, we would have had to use SYS_CONNECT_BY_PATH for this, but starting in Oracle 10 we have CONNECT_BY_ROOT.
WITH top_level_folders AS
SELECT c.dataid
, c.name
FROM dtree p
JOIN dtree c ON c.parentid = p.dataid
WHERE p.name = 'root'
, active_files AS
SELECT CONNECT_BY_ROOT dataid AS top_dataid
, CONNECT_BY_ROOT name AS top_name
, dataid
FROM dtree
WHERE name LIKE 'Activefile%'
START WITH dataid IN (
SELECT dataid
FROM top_level_folders
CONNECT BY parentid = PRIOR dataid
SELECT dataid
, name
FROM top_level_folders
MINUS
SELECT af.top_dataid
, af.top_name
FROM active_files af
JOIN dauditnew dan ON af.dataid = dan.dataid
WHERE dan.auditdate > SYSDATE - 90
ORDER BY dataid
;Output (when run on Feb. 2, 2012):
` DATAID NAME
2 folder1
3 folder2
5 folder4As you can see, I did the filtering for audit dates near the end of the query. Depending on your data and your requirements, there might be a more efficient way to do it near the start of the query. The CONNECT BY is probably going to be the slow part of his job, so if there's some way to eliminate rows before that, it would probably be more efficient that running a longer CONNECT BY part, only to discard some of the results at the end. You don't want to do a join in the same sub-query as the CONNECT BY; that's extremely inefficient.
I still have no idea why your original query was getting that ORA-30004 error. I'd be interested in finding out. I can't run the original query, apparantly because you simplified the tables for posting. If you can post a test case that gets the error using SYS_CONNECT_BY_PATH, I'll see if I can find out what caused it. -
SYS_CONNECT_BY_PATH performance issue!!
I am using SYS_CONNECT_BY_PATH to get the hierarchical structure from a table. But its taking much much more time.
I am using as follows:
SELECT DISTINCT trim(h.my_id) AS my_ID,sys_connect_by_path (trim(my_id),'.') AS hierarchy
from (some inline select query) h
connect by prior h.my_id=h.super_id
Please someone advice me if there is any way for optimizing sys_connect_by_path() in general. Thanks.Hi,
If you don't have a START WITH clause, you'll start with every row in your table. Is that really what you need to do?
It's also very suspicious that you need SELECT DISTINCT. SELECT DISTINCT is sometimes an attempt to conceal the defects caused by a problem elsewhere (such as lacking a START WITH clause).
Please explain exactly what you're trying to do. Post a little sample data and the results you need to get from that data. -
Sys_connect_by_path problem
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE 11.1.0.7.0 Production
TNS for IBM/AIX RISC System/6000: Version 11.1.0.7.0 - ProductionHow come
SYS_CONNECT_BY_PATH (file_name, ',#')works fine but
SYS_CONNECT_BY_PATH (file_name, ',' || '#')fails with a
ORA-30003: illegal parameter in SYS_CONNECT_BY_PATH functionerror? Can anyone provide some explanation?
Thanks.REPLACE would work on SYS_CONNECT_BY_PATH results as well, afaik.
Using some example that I found in my cache:
SQL> with table1 as (
2 select 10001 afield, 'Test Record 1' bfield, 'Hello' cfield from dual union all
3 select 10002, 'Test Record 2', 'Hello' from dual union all
4 select 10003, 'Test Record 3', 'Hello' from dual
5 )
6 , table2 as (
7 select '00001' afield, 'Sample Data 1' bfield, 10001 cfield from dual union all
8 select '00002', 'Sample Data 2', 10001 from dual union all
9 select '00003', 'Sample Data 3a', 10002 from dual union all -- Duplicate
10 select '00003', 'Sample Data 3b', 10002 from dual union all -- Duplicate
11 select '00004', 'Sample Data 4', 10003 from dual union all
12 select '00005', 'Sample Data 5', 10003 from dual union all
13 select '00006', 'Sample Data 6', 10003 from dual
14 )
15 --
16 -- actual query:
17 --
18 select afield
19 , bfield
20 , ltrim(sys_connect_by_path(bafield, ',')) scbp1
21 --, ltrim(sys_connect_by_path(bafield, chr(10)), chr(10)) scbp2 --<< gives an ora-30003
22 , replace(ltrim(sys_connect_by_path(bafield, ','), ','), ',', chr(10)) scbp3
23 from ( select a.afield
24 , a.bfield
25 , b.afield bafield
26 , row_number() over (partition by a.afield order by to_number(b.afield)) rn
27 , count(distinct b.afield) over (partition by a.afield) recs
28 from table1 a
29 , table2 b
30 where a.afield = b.cfield
31 )
32 where rn=recs
33 start with rn=1
34 connect by afield = prior afield
35 and rn = prior rn+1;
AFIELD BFIELD SCBP1 SCBP3
10001 Test Record 1 ,00001,00002 00001
00002
10002 Test Record 2 ,00003 00003
10003 Test Record 3 ,00004,00005,00006 00004
00005
00006
3 rows selected.Docs say:
"Both column and char can be any of the datatypes CHAR, VARCHAR2, NCHAR, or NVARCHAR2. The string returned is of VARCHAR2 datatype and is in the same character set as column."
http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions171.htm#SQLRF06116
So, I guess 'char' just cannot be an expression (or a subquery or a function or containing operators etc...). -
SYS_CONNECT_BY_PATH Upside-down (over Bills of Material)
Hello all,
I'm trying to use this function, in order to check the most upper assemblies for a component.
The input I enter us a lower component, which I'd like to know who it the top assembly for it.
I'm using the following select:
select distinct(LPAD(' ', 2*level-1)||SYS_CONNECT_BY_PATH((mcil_fe_work_plan.get_item_name(asy.assembly_item_id,2)), '/')) "Hierarchy",
mcil_fe_work_plan.get_item_name(com.component_item_id,2) "Last level"
from bom_bill_of_materials asy, bom_inventory_components com
where asy.bill_sequence_id = com.bill_sequence_id
start with com.component_item_id = 73805
connect by NOCYCLE prior asy.assembly_item_id = com.component_item_id
I'm getting thousands of line, for example:
/FLF5559A/F2180A/INFOTAC F2180A
/FLF5559A/FUF1025A FLF5559A
/FLF5559A/FUF1602A FLF5559A
/FLF5559A/FUF1602A/F5110A/F5110A-MM/F5110A-MM*12382 F5110A-MM
/FLF5559A/FUF1602A/F5110A/F5110ASP96910/F5110ASP96910-MM F5110ASP96910
/FLF5559A/FUF1602A/F5110A/F5110A-MM*8036 F5110A
/FLF5559A/FUF1602A/F5149B/F5149B-MM/F5149_-MDL/F5149_ F5149_-MDL
I want to know Only the top level assembly, not only one level above or to get all the tree's structure.
Any idea guyes?
Best Regards,
Tomer.
Edited by: tomeriko on Mar 24, 2009 1:07 AMSCOTT schema is installed as standard with Oracle although the user login may be locked initially unless the DBA has unlocked it.
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7839 KING PRESIDENT 17-NOV-81 5000 10
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7934 MILLER CLERK 7782 23-JAN-82 1300 10
14 rows selected.
SQL> col d_ename format a20
SQL> col path format a30
SQL> col a_ename format a20
SQL> ed
Wrote file afiedt.buf
1 SELECT CONNECT_BY_ROOT ename AS d_ename
2 , SYS_CONNECT_BY_PATH (ename, '/') AS path -- For illustration only
3 , ename AS a_ename
4 FROM scott.emp
5 WHERE CONNECT_BY_ISLEAF = 1
6 START WITH ename = '&starting_ename'
7* CONNECT BY empno = PRIOR mgr
SQL> /
Enter value for starting_ename: SCOTT
old 6: START WITH ename = '&starting_ename'
new 6: START WITH ename = 'SCOTT'
D_ENAME PATH A_ENAME
SCOTT /SCOTT/JONES/KING KING
SQL>;) -
Help with sys_connect_by_path
Hi,
I'm newbie in retrieving hierarchical data, so please help with this.
I have Oracle 8.1.7.0.0.
I have a view with this kind of data:
TYP COMP_TYP
005 010
010 005
020 010
030 010
030 020
040 005
060 040
065 005
070 19
080 070
090 070
095 030
095 060
095 065
100 005
100 030
100 060
100 065
Now, the client wants to see these data in hierarchical way.
I tried this:
SELECT
LPAD(' ', 2*LEVEL, ' ' ) ||cbc.TYP TYP
,sys_connect_by_path( cbc.COMP_TYP, '/' ) COMP_TYP
FROM v_cls_test cbc
START WITH cbc.TYP='095'
CONNECT BY PRIOR cbc.TYP = cbc.COMP_TYP
in this case the desired result should be like
095
030
010
005
020
010
060
040
005
065
005
but I'm not getting the desired result.
Thanks in advance for any input.
Best regards,
MariusHi,
There is a problem with your data
TYP COMP_TYP
005 010 --> should this pair be 005 NULL ?? otherwise it's circullar
010 005
If you change the first pair one to 005 NULL and modify your query as follows:
SELECT
LPAD(' ', 2*LEVEL, ' *' ) ||cbc.TYP TYP
,sys_connect_by_path( cbc.TYP, '/' ) PATH
FROM v_cls_test cbc
START WITH cbc.COMP_TYPE IS NULL
CONNECT BY PRIOR cbc.TYP = cbc.COMP_TYP
you'll get the following output
TYP PATH
* 005 /005
*** 010 /005/010
***** 020 /005/010/020
******* 030 /005/010/020/030
********* 095 /005/010/020/030/095
********* 100 /005/010/020/030/100
Rado -
Pivoting using sys_connect_by_path
Can you please let me know how to get this output using sys_connect_by_path hierarchical function ?
JOB DEPT_10 DEPT_20 DEPT_30 DEPT_40
CLERK 1 2 1 (null)
SALESMAN (null) (null) 4 (null)
PRESIDENT 1 (null) (null) (null)
MANAGER 1 1 1 (null)
ANALYST (null) 2 (null) (null)
I know how to acheive this by decode function.Even I have the query ready .
select job,
max( decode( deptno, 10, cnt, null ) ) dept_10,
max( decode( deptno, 20, cnt, null ) ) dept_20,
max( decode( deptno, 30, cnt, null ) ) dept_30,
max( decode( deptno, 40, cnt, null ) ) dept_40
from ( select job, deptno, count(*) cnt from emp group by job, deptno )
group by job
But my requirement is to get the same output by using SYS_CONNECT_BY_PATH.
Please let me know the query if its possible.Else let me know the reason why we cant do .Hi,
Welcome to thre forum!
If you're using Oracle 11, then SELECT ... PIVOT can help do what you want. In any version, you can do something like what you're already doing, though you don't need a sub-query:
SELECT job
, SUM (DECODE (deptno, 10, 1)) AS dept_10
, SUM (DECODE (deptno, 20, 1)) AS dept_20
, SUM (DECODE (deptno, 30, 1)) AS dept_30
, SUM (DECODE (deptno, 40, 1)) AS dept_40
FROM scott.emp
GROUP BY job
ORDER BY job -- If wanted
;Either way, SYS_CONNECT_BY_PATH doesn't help any.
The one reason why you might want to use SYS_CONNECT_BY_PATH is if you didn't know how many different departments there might be. In that case, you could do something like this:
WITH got_cnt AS
SELECT e.job
, d.deptno
, NULLIF (COUNT (e.deptno), 0) AS cnt
, DENSE_RANK () OVER (ORDER BY d.deptno) AS d_num
FROM scott.dept d
LEFT OUTER JOIN scott.emp e PARTITION BY (e.job)
ON d.deptno = e.deptno
GROUP BY e.job
, d.deptno
SELECT job
, REPLACE ( SYS_CONNECT_BY_PATH ( NVL2 ( cnt
, TO_CHAR (cnt, '9999')
) AS all_cnts
FROM got_cnt
WHERE CONNECT_BY_ISLEAF = 1
START WITH d_num = 1
CONNECT BY d_num = PRIOR d_num + 1
AND job = PRIOR job
ORDER BY job
;As you can see, it's quite a bit more complicated than what you already have, and it's less efficient.
Also, it doesn't produce separate columns for each depararment. All the departments are concatenated together, formatted so they look like separate columns. Also, the query above doesn't have a header identifiyuing which department corresponds to each "column" , but you could fix that by doing a UNION with another CONNECT BY query to generate a header row.
To get truly separate columns, you could use various string manipulation techniques to split the results of SYS_CONNECT_BY_PATH into separate columns, but that requires knowing exactly how many departments to expect, which defeats the purpose of using SYS_CONNECT_BY_PATH. -
Sys_connect_by_path over db link causes ora-29900
I have a query that uses sys_connect_by_path. It works fine when run from the database where the table resides. When I try to run the same query from another database over a db link, I get the following error:
ora-29900: operator binding does not exist
ora-06553: pls-306: wrong number or types of arguments in call to 'PATH'
Any ideas? Workarounds?Are the two databases running the same Oracle version?
-
SQL Query help ( On connect By level clause)
Hi all,
I have this query developed with data in with clause.
With dat As
select '@AAA @SSS @DDD' col1 from dual union all
select '@ZZZ @XXX @TTT @RRR @ZZA' col1 from dual
Select regexp_substr( col1 , '[^@][A-Z]+',1,level) Show from dat
connect by level <= regexp_count(col1, '@');Current output :-
SHOW
AAA
SSS
DDD
RRR
ZZA
TTT
RRR
ZZA
XXX
DDD
RRR
SHOW
ZZA
TTT
RRR
ZZA
. . .1st row comes fine, But next row data is getting duplicated. And total record count = 30. I tried with some but didn't work.
Expected output :-
SHOW
AAA
SSS
DDD
ZZZ
XXX
TTT
RRR
ZZAI need some change on my query and I am not able to find that. So anybody can add on that or can also provide some different solution too.
Thanks!
AshutoshHi,
When you use something like "CONNECT BY LEVEL <= x", then at least one of the following must be true:
(a) the table has no more than 1 row
(b) there are other conditions in the CONNECT BY clause, or
(c) you know what you are doing.
To help see why, run this query
SELECT SYS_CONNECT_BY_PATH (dname, '/') AS path
, LEVEL
FROM scott.dept
CONNECT BY LEVEL <= 3
;and study the results:
PATH LEVEL
/ACCOUNTING 1
/ACCOUNTING/ACCOUNTING 2
/ACCOUNTING/ACCOUNTING/ACCOUNTING 3
/ACCOUNTING/ACCOUNTING/RESEARCH 3
/ACCOUNTING/ACCOUNTING/SALES 3
/ACCOUNTING/ACCOUNTING/OPERATIONS 3
/ACCOUNTING/RESEARCH 2
/ACCOUNTING/RESEARCH/ACCOUNTING 3
/ACCOUNTING/RESEARCH/RESEARCH 3
/ACCOUNTING/RESEARCH/SALES 3
/ACCOUNTING/RESEARCH/OPERATIONS 3
/ACCOUNTING/SALES 2
/ACCOUNTING/SALES/ACCOUNTING 3
84 rows selected. -
Help: How to create a query that transpose the column content?
Here, suppose that I have two tables
TAB_A:
ID TYPE
1 AA
1 AB
1 AC
2 BA
2 BB
2 BC
2 BD
I'd like to create a query that gives result as:
ID TYPE
1 AA AB AC
2 BA BB BC BD Any suggestions?
Thank you in advance.
JimmyHi
Try this:
SELECT id,
replace(LTRIM(MAX(SYS_CONNECT_BY_PATH(type,'*'))
KEEP (DENSE_RANK LAST ORDER BY curr),'*'),'*', ', ') AS type
FROM (SELECT id, type,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY type) AS curr,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY type) -1 AS prev
FROM tab_a)
GROUP BY id
CONNECT BY prev = PRIOR curr AND id = PRIOR id
START WITH curr = 1;
Ott Karesz
http://www.trendo-kft.hu -
How To Concatenate Column Values from Multiple Rows into a Single Column?
How do I create a SQL query that will concatenate column values from multiple rows into a single column?
Last First Code
Lesand Danny 1
Lesand Danny 2
Lesand Danny 3
Benedi Eric 7
Benedi Eric 14
Result should look like:
Last First Codes
Lesand Danny 1,2,3
Benedi Eric 7,14
Thanks,
David JohnsonStarting with Oracle 9i
select last, first, substr(max(sys_connect_by_path(code,',')),2) codes
from
(select last, first, code, row_number() over(partition by last, first order by code) rn
from a)
connect by last = prior last and first = prior first and prior rn = rn -1
start with rn = 1
group by last, first
LAST FIRST CODES
Lesand Danny 1,2,3
Benedi Eric 7,14Regards
Dmytro -
Concatenating values in one row
I need to write a function that will give me a concatenated list of all the records where gurmail_matl_code_mod like '8%'
This query is giving me those results:
GURMAIL_PIDM CODE1 CODE2
1135711
1135711 8IBD
1135711 8IBW
I want something like this 1135711 8IBW 8IBD in one row.
select
gurmail_pidm,
max(decode(rn,1,gurmail_matl_code_mod )) code1,
max(decode(rn,2,gurmail_matl_code_mod )) code2
from (select gurmail_pidm,
gurmail_matl_code_mod,
row_number() over (partition by gurmail_pidm order by gurmail_matl_code_mod desc) rn
from
(select gurmail_pidm,gurmail_matl_code_mod
from saturn.spriden,
general.gurmail
where spriden_pidm = gurmail_pidm
and spriden_change_ind is null
and gurmail_matl_code_mod like '8%'
and gurmail_pidm = 1135711
and GURMAIL_DATE_PRINTED is null
and gurmail_matl_code_mod is not null))
group by gurmail_pidm, gurmail_matl_code_mod How I can modify this query or let me know if you have other ideas..
Thank youHello
try this,
SQL> with tab as(Select 1135711 GURMAIL_PIDM, Null CODE1 from dual Union All
2 Select 1135711 GURMAIL_PIDM, '8IBD' CODE1 from dual Union All
3 Select 1135711 GURMAIL_PIDM, '8IBW' CODE1 from dual)
4 SELECT GURMAIL_PIDM || sys_connect_by_path(CODE1,' ') Result
5 FROM (SELECT GURMAIL_PIDM
6 ,code1
7 ,row_number() over(Partition BY GURMAIL_PIDM Order BY GURMAIL_PIDM) rn
8 FROM tab)
9 WHERE connect_by_isleaf = 1
10 Start With rn = 1
11 Connect BY Prior rn = rn - 1;
RESULT
1135711 8IBW 8IBDHope this helps
Christian Balz
Maybe you are looking for
-
How do i add memory to my imac?
I plan on buying 1gb of Ram to add to my iMAC, however i don't see any spot on the system where the RAM card would fit in. The last thing I want to do is buy the memory and have no idea how to apply it so can anyone tell me like a step by step proced
-
There are 2 printers on the system. I want to create a Print Button, so that if the user clicks it, a desired area prints on a specific printer. Thanks for your consideration.
-
Event triggering after Sales Order is created
Hi All, I have a requirement where i need to update the SO created to a table in another system by making RFC call. As RFC will take time to compete, the user doesn't want to keep the SO open for that much time. We want to avoid user exit for this re
-
Having problems cloning a new hard drive to install in Macbook Pro 2012
I have a 2009 MBP and I just bought a Crucial 256GB SSD drive. I have cloned it a couple of ways (SuperDuper & CCC) and also tried installing my MBP hybrid drive into the new 2012 MBP. Nothing I have tried has worked. What happens is when I boot I he
-
Hi Techies, while creating a BP in CRM by default it is picking 2 Roles. One is <b>Consumer</b> & second is <b>BP (General)</b>. I need to assign another additonal role <b>Contact Person</b> while creating the same. Is there any BADI for Partner cr