Home » SQL & PL/SQL » SQL & PL/SQL » Oracle pair combination with two column values in a table (Oracle 11g)
Oracle pair combination with two column values in a table [message #642001] Sat, 29 August 2015 11:45 Go to next message
sunshine
Messages: 7
Registered: August 2015
Junior Member
I have oracle table with 2 columns

column1 column2
A B
B C
D E
C F
need output to have groups for chained member combination pairs, group number is assigned based on the combination of pairs , as D and E are not repeated so they are assigned to one group,
A comes with B, B comes with C and C comes with F, all of them have some kind of relation so they should assign to one unique group number , desired output is given below
Column Group
A 1
B 1
C 1
F 1
D 2
E 2
please let me know sql or plsql
Re: Oracle pair combination with two column values in a table [message #642002 is a reply to message #642001] Sat, 29 August 2015 11:52 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
Welcome to this forum.

Please read and follow the forum guidelines, to enable us to help you:
OraFAQ Forum Guide
How to use {code} tags and make your code easier to read

Re: Oracle pair combination with two column values in a table [message #642003 is a reply to message #642002] Sat, 29 August 2015 12:09 Go to previous messageGo to next message
sunshine
Messages: 7
Registered: August 2015
Junior Member
(updated with formatting)
I have oracle table with 2 columns with values below
column1  column2                                                        
 A        B
 B        C
 D        E
 C        F

need output to have groups for chained member combination pairs, group number is assigned based on the combination of pairs , as D and E are not repeated so they are assigned to one group,
A comes with B, B comes with C and C comes with F, all of them have some kind of relation(occurances) so they should assign to one unique group number , desired output is given below
Column Group
A         1
B         1
C         1
F         1
D         2
E         2

please let me know sql or plsql

[Updated on: Sat, 29 August 2015 12:11]

Report message to a moderator

Re: Oracle pair combination with two column values in a table [message #642004 is a reply to message #642003] Sat, 29 August 2015 12:46 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Recursive SQL solution:

with r(
       col,
       grp
      ) as (
             select  column1 col,
                     row_number() over(order by column1) grp
               from  tbl
               where column1 not in (select column2 from tbl)
            union all
             select  t.column2,
                     r.grp
               from  r,
                     tbl t
               where t.column1 = r.col
           )
select  col,
        grp
  from  r
  order by grp,
           col
/

C        GRP
- ----------
A          1
B          1
C          1
F          1
D          2
E          2

6 rows selected.

SQL>


SY.
Re: Oracle pair combination with two column values in a table [message #642008 is a reply to message #642004] Sat, 29 August 2015 13:56 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Hierarchical query solution:
SQL> with
  2    data as (
  3      select col1, col2, connect_by_root col1 grp
  4      from t
  5      connect by prior col2 = col1
  6      start with col1 not in (select col2 from t)
  7  )
  8  select col1, dense_rank() over (order by grp) grp
  9  from data
 10  union
 11  select col2, dense_rank() over (order by grp) grp
 12  from data
 13  order by 2, 1
 14  /
COL        GRP
--- ----------
A            1
B            1
C            1
F            1
D            2
E            2

Re: Oracle pair combination with two column values in a table [message #642009 is a reply to message #642008] Sat, 29 August 2015 13:58 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Or better:
SQL> with
  2    data as (
  3      select col1, col2,
  4             dense_rank() over (order by connect_by_root col1) grp
  5      from t
  6      connect by prior col2 = col1
  7      start with col1 not in (select col2 from t)
  8  )
  9  select col1, grp
 10  from data
 11  union
 12  select col2, grp
 13  from data
 14  order by 2, 1
 15  /
COL        GRP
--- ----------
A            1
B            1
C            1
F            1
D            2
E            2

Re: Oracle pair combination with two column values in a table [message #642010 is a reply to message #642009] Sat, 29 August 2015 14:48 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Or:

with data as (
              select  connect_by_root column1 root,
                      column2
                 from tbl
                 connect by prior column2 = column1
                 start with column1 not in (select column2 from tbl)
             )
select  nvl(column2,root) col,
        dense_rank() over(order by root) grp
  from  data
  group by grouping sets((root),(root,column2))
  order by grp,
           col
/

C        GRP
- ----------
A          1
B          1
C          1
F          1
D          2
E          2

6 rows selected.

SQL>


SY.
Re: Oracle pair combination with two column values in a table [message #642013 is a reply to message #642001] Sat, 29 August 2015 23:13 Go to previous messageGo to next message
sunshine
Messages: 7
Registered: August 2015
Junior Member
Thanks SY and MC, I really appreciate your prompt responses
let me explain little more detail on the scenarios below

Create table t(col1 varchar2(1),col2 varchar2(1));
insert into t values('A','B');
insert into t values('B','C');
insert into t values('D','E');
insert into t values('C','F');
insert into t values('A','F');
insert into t values('F','A');
insert into t values('H','I');
insert into t values('I','J');
insert into t values('Z','J');
insert into t values('X','Y');

SELECT * FROM T;
COL1   COL2
A	B
B	C
D	E
H	I
I	J
Z	J
F	A
C	F
X	Y

as you can see A, B in row#1 and B, C in row#2 have B common and in row#7 and row#8 F came with A and C , all pairs have some connection, so we have A,B,C,F members in one group
D,E in one group as (D and E appeared once)
H,I,J,Z in one group
and X,Y in one group
so the desired output need to be is given below
char    grp
 A       1
 B       1  
 C       1
 F       1 
 D       2
 E       2
 H       3
 I       3
 J       3
 Z       3
 X       4 
 Y       4


please assist in SQL or PLSQL, thanks
Re: Oracle pair combination with two column values in a table [message #642019 is a reply to message #642013] Sun, 30 August 2015 08:55 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Not much of a difference:

with t1 as (
            select  distinct least(column1,column2) column1,
                    greatest(column1,column2) column2
              from  tbl
           ),
   data as (
              select  connect_by_root column1 root,
                      column2
                 from t1
                 connect by prior column2 = column1
                 start with column1 not in (select column2 from t1)
             )
select  nvl(column2,root) col,
        dense_rank() over(order by root) grp
  from  data
  group by grouping sets((root),(root,column2))
  order by grp,
           col
/

C        GRP
- ----------
A          1
B          1
C          1
F          1
D          2
E          2
H          3
I          3
J          3
Z          3
X          4

C        GRP
- ----------
Y          4

12 rows selected.

SQL>


SY.
Re: Oracle pair combination with two column values in a table [message #642020 is a reply to message #642001] Sun, 30 August 2015 10:34 Go to previous messageGo to next message
sunshine
Messages: 7
Registered: August 2015
Junior Member
Thanks SY,
please see one more scenario given below is not qualifying, if we insert two more rows in existing table e.g.
insert into t values('M','K');
insert into t values('M','L');

K,L,M supposed to be collected in one group, but the query result shows two groups

C      GRP
A	1
B	1
C	1
F	1
D	2
E	2
H	3
I	3
J	3
Z	3
K	4
M	4
L	5
M	5
X	6
Y	6  

please help
Re: Oracle pair combination with two column values in a table [message #642024 is a reply to message #642020] Sun, 30 August 2015 18:16 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
I'd suggest changing design since your design stores both upstream and downstream hierarchy in same table. Don't have much time for a better solution, so:

with t1 as (
            select  distinct least(column1,column2) column1,
                             greatest(column1,column2) column2
              from  tbl
           ),
     t2 as (
              select  connect_by_root column1 root,
                      column1,
                      column2,
                      count(*) over(partition by connect_by_root column1) cnt
                 from t1
                 connect by prior column2 = column1
                 start with column1 not in (select column2 from t1)
             ),
    t3 as (
            select  distinct greatest(column1,column2) column1,
                             least(column1,column2) column2
              from  tbl
           ),
     t4 as (
              select  connect_by_root column1 root,
                      column1,
                      column2,
                      count(*) over(partition by connect_by_root column1) cnt
                 from t3
                 connect by prior column2 = column1
                 start with column1 not in (select column2 from t3)
             ),
     t5 as (
             select  least(column1,column2) column1,
                     greatest(column1,column2) column2,
                     root,
                     cnt,
                     1 flag
               from  t2
            union all
             select  least(column1,column2) column1,
                     greatest(column1,column2) column2,
                     root,
                     cnt,
                     2 flag
               from  t4
           ),
     t6 as (
            select  case min(flag) keep(dense_rank last order by cnt)
                      when 1 then column2
                      else column1
                    end col,
                    min(root) keep(dense_rank last order by cnt,flag desc) root
              from  t5
              group by column1,
                       column2
           )
select  nvl(col,root) col,
        dense_rank() over(order by root) grp
  from  t6
  group by grouping sets((root),(root,col))
  order by grp,
           col
/

C        GRP
- ----------
A          1
B          1
C          1
F          1
D          2
E          2
H          3
I          3
J          3
Z          3
K          4

C        GRP
- ----------
L          4
M          4
X          5
Y          5

15 rows selected.

SQL>


SY.

[Updated on: Sun, 30 August 2015 18:23]

Report message to a moderator

Re: Oracle pair combination with two column values in a table [message #642025 is a reply to message #642024] Sun, 30 August 2015 19:38 Go to previous messageGo to next message
sunshine
Messages: 7
Registered: August 2015
Junior Member
Thank you very much SY ,that's what i was expecting in the resultset, it was a great help!
Re: Oracle pair combination with two column values in a table [message #642032 is a reply to message #642025] Mon, 31 August 2015 11:52 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
SQL> with
  2    data as ( select least(col1,col2) col1, greatest(col1,col2) col2 from t ),
  3    all_paths as (
  4      select sys_connect_by_path(col1,'/')||'/'||col2||'/' path
  5      from data
  6      where connect_by_isleaf = 1
  7      connect by prior col2 = col1
  8      start with col1 not in (select col2 from data)
  9    ),
 10    grouped as (
 11      select a.col1, a.col2, listagg(b.path) within group (order by b.path) path
 12      from data a, all_paths b
 13      where b.path like '%/'||a.col1||'/%'
 14         or b.path like '%/'||a.col2||'/%'
 15      group by a.col1, a.col2
 16    ),
 17    split as (
 18      select distinct
 19             col1, col2, regexp_substr(path, '[^/]+', 1, column_value) elem
 20      from grouped,
 21           table(cast(multiset(select level from dual
 22                               connect by level <= regexp_count(path,'/'))
 23                      as sys.odciNumberList))
 24      where regexp_substr(path, '[^/]+', 1, column_value) is not null
 25    ),
 26    result as (
 27      select col1, col2,
 28             dense_rank()
 29               over (order by listagg(elem,',') within group (order by elem))
 30               grp
 31      from split
 32      group by col1, col2
 33    )
 34  select distinct nvl(col1,col2) col, grp
 35  from result
 36  group by cube(col1, col2, grp)
 37  having grouping(grp)=0 and ( grouping(col1)=0 or grouping(col2)=0 )
 38  order by 2, 1
 39  /
C        GRP
- ----------
A          1
B          1
C          1
F          1
D          2
E          2
H          3
I          3
J          3
Z          3
K          4
L          4
M          4
X          5
Y          5

15 rows selected.

Re: Oracle pair combination with two column values in a table [message #642037 is a reply to message #642032] Mon, 31 August 2015 22:53 Go to previous messageGo to next message
sunshine
Messages: 7
Registered: August 2015
Junior Member
Thanks and appreciated!
Re: Oracle pair combination with two column values in a table [message #642043 is a reply to message #642037] Tue, 01 September 2015 01:14 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

A slightly better solution is:
SQL> with
  2    data as ( select least(col1,col2) col1, greatest(col1,col2) col2 from t ),
  3    all_paths as (
  4      select sys_connect_by_path(col1,'/')||'/'||col2||'/' path
  5      from data
  6      where connect_by_isleaf = 1
  7      connect by prior col2 = col1
  8      start with col1 not in (select col2 from data)
  9    ),
 10    grouped as (
 11      select a.col1, a.col2, listagg(b.path) within group (order by b.path) path
 12      from data a, all_paths b
 13      where b.path like '%/'||a.col1||'/%'
 14         or b.path like '%/'||a.col2||'/%'
 15      group by a.col1, a.col2
 16    ),
 17    split as (
 18      select distinct
 19             col1, col2, regexp_substr(path, '[^/]+', 1, column_value) elem
 20      from grouped,
 21           table(cast(multiset(select level from dual
 22                               connect by level <= regexp_count(path,'/'))
 23                      as sys.odciNumberList))
 24      where regexp_substr(path, '[^/]+', 1, column_value) is not null
 25    ),
 26    result as (
 27      select col1, col2,
 28             dense_rank()
 29               over (order by listagg(elem,',') within group (order by elem))
 30               grp
 31      from split
 32      group by col1, col2
 33    )
 34  select distinct nvl(col1,col2) col, grp
 35  from result
 36  group by grouping sets((grp,col1),(grp,col2))
 37  order by 2, 1
 38  /
C  GRP
- ----
A    1
B    1
C    1
F    1
D    2
E    2
H    3
I    3
J    3
Z    3
K    4
L    4
M    4
X    5
Y    5

15 rows selected.

Re: Oracle pair combination with two column values in a table [message #645434 is a reply to message #642001] Sun, 06 December 2015 15:56 Go to previous message
sunshine
Messages: 7
Registered: August 2015
Junior Member
Hi there,

Thanks for the replies, tried all the solutions , with more than 25 members in a group, performance is really bad, almost not working, is there any better way to write pl/sql, looping, arrays to handle large volume of data sets

thanks and appreciated
Previous Topic: Regular Expression
Next Topic: Compilation error in Function
Goto Forum:
  


Current Time: Wed Apr 24 15:07:12 CDT 2024