-1

In oracle Query either pure SQL or PLSQL, is that possible with the given source table to have the expected result? Thanks

Source Table:

Col_Old_ID  Col_New_ID
ID_1        ID_2
ID_2        ID_3
ID_A        ID_B
ID_B        ID_C
ID_3        ID_4
ID_4        ID_5
ID_C        ID_D

Expected Result:

ID             History
ID_1           ID_1,ID_2,ID_3,ID_4,ID_5
ID_2           ID_1,ID_2,ID_3,ID_4,ID_5
ID_3           ID_1,ID_2,ID_3,ID_4,ID_5
ID_4           ID_1,ID_2,ID_3,ID_4,ID_5
ID_5           ID_1,ID_2,ID_3,ID_4,ID_5
ID_A           ID_A,ID_B,ID_C,ID_D
ID_B           ID_A,ID_B,ID_C,ID_D
ID_C           ID_A,ID_B,ID_C,ID_D
ID_D           ID_A,ID_B,ID_C,ID_D
Lee Jack
  • 3
  • 2
  • I still finding way to format the question, sorry about that i now in this forum. @a_horse_with_no_name sorry is 11g – Lee Jack Apr 19 '18 at 09:13
  • @a_horse_with_no_name, hi thanks for your helped, but i would like say i cant find the answer match with my case in other post, because my expected History is all same value with ID_1 until ID_4. But most of the given result is different. – Lee Jack Apr 19 '18 at 09:21

1 Answers1

1

SQL Fiddle

Oracle 11g R2 Schema Setup:

CREATE TABLE table_name ( Col_Old_ID, Col_New_ID ) AS
SELECT 'ID_1',        'ID_2' FROM DUAL UNION ALL
SELECT 'ID_2',        'ID_3' FROM DUAL UNION ALL
SELECT 'ID_A',        'ID_B' FROM DUAL UNION ALL
SELECT 'ID_B',        'ID_C' FROM DUAL UNION ALL
SELECT 'ID_3',        'ID_4' FROM DUAL UNION ALL
SELECT 'ID_4',        'ID_5' FROM DUAL UNION ALL
SELECT 'ID_C',        'ID_D' FROM DUAL;

Query 1: You can use a hierarchical query to get the history from the current row:

SELECT CONNECT_BY_ROOT( Col_Old_ID ) AS Id,
       CONNECT_BY_ROOT( Col_Old_ID )
         || SYS_CONNECT_BY_PATH( Col_New_ID, ',' ) AS History
FROM   table_name
WHERE  CONNECT_BY_ISLEAF = 1
CONNECT BY PRIOR Col_New_ID = Col_Old_ID

Results:

|   ID |                  HISTORY |
|------|--------------------------|
| ID_1 | ID_1,ID_2,ID_3,ID_4,ID_5 |
| ID_2 |      ID_2,ID_3,ID_4,ID_5 |
| ID_3 |           ID_3,ID_4,ID_5 |
| ID_4 |                ID_4,ID_5 |
| ID_A |      ID_A,ID_B,ID_C,ID_D |
| ID_B |           ID_B,ID_C,ID_D |
| ID_C |                ID_C,ID_D |

Query 2: If you want the full history then it gets complicated as you need the hierarchy before and after the item.

SELECT id,
       HISTORY
FROM   (
  SELECT Col_Old_ID,
         Col_new_id,
         MAX(
           SUBSTR( SYS_CONNECT_BY_PATH( Col_Old_ID, ',' ), 2 )
             || ',' || Col_New_ID
         ) OVER (
           PARTITION BY CONNECT_BY_ROOT( Col_Old_ID )
           ORDER BY     CONNECT_BY_ISLEAF DESC
         ) As history,
         CONNECT_BY_ISLEAF AS leaf
  FROM   table_name
  START WITH Col_Old_ID NOT IN ( SELECT Col_New_Id FROM table_name )
  CONNECT BY PRIOR Col_New_ID = Col_Old_ID
)
UNPIVOT ( id FOR col_type IN ( Col_Old_Id, Col_New_Id ) )
WHERE col_type = 'COL_OLD_ID'
OR    leaf = 1
ORDER BY id

Results:

|   ID |                  HISTORY |
|------|--------------------------|
| ID_1 | ID_1,ID_2,ID_3,ID_4,ID_5 |
| ID_2 | ID_1,ID_2,ID_3,ID_4,ID_5 |
| ID_3 | ID_1,ID_2,ID_3,ID_4,ID_5 |
| ID_4 | ID_1,ID_2,ID_3,ID_4,ID_5 |
| ID_5 | ID_1,ID_2,ID_3,ID_4,ID_5 |
| ID_A |      ID_A,ID_B,ID_C,ID_D |
| ID_B |      ID_A,ID_B,ID_C,ID_D |
| ID_C |      ID_A,ID_B,ID_C,ID_D |
| ID_D |      ID_A,ID_B,ID_C,ID_D |
MT0
  • 143,790
  • 11
  • 59
  • 117
  • Hi, thanks your respond, but i the result that i want is the history have same result for ID_1 until ID_4, but your given result is not what i want. – Lee Jack Apr 19 '18 at 09:16
  • @LeeJack Updated – MT0 Apr 19 '18 at 09:35
  • Thanks!!! this the result i expect for.....i search a lot forum but not able to find this. finally i get it here...thanks!!! – Lee Jack Apr 19 '18 at 09:37
  • Hi, i have try out in my query, is have around 300,000 record and give me about 614,944,004 cost. is that possible to tune this? – Lee Jack Apr 19 '18 at 09:44
  • @LeeJack I've tuned it a lot but it probably can be tuned more - have a go and post a new answer if you find something more efficient. – MT0 Apr 19 '18 at 09:45
  • have a go and post a new answer what do you mean? you mean create another post? sorry i new at here. I have tested the your solution, it only can handle 7000records+- more then that it will create a very high cost. – Lee Jack Apr 19 '18 at 09:53
  • You have a hierarchical data structure with no easily way to pick out a root and you want to aggregate over the hierarchy; what did you expect to happen to the cost as the number of data points grows? I've used a single table scan for the hierarchical query and a single table scan with an anti-join to find the roots of the hierarchy beyond that there is not much to optimise. Please see if you, @LeeJack, can find a better solution and you post it as a new answer but I don't have your data and am volunteering my time so can't optimise it further than I have. Good luck. – MT0 Apr 19 '18 at 10:15
  • hi, thanks for your feedback, i will try to find tune, see is that possible way to lower the cost or not. thanks again i learn alot from your answer. – Lee Jack Apr 19 '18 at 10:20