-1

I have a column as below. there are multiple columns like this with different data. enter image description here

I need output like this

enter image description here

I need values that inside | | symbols. I tried like below But not successes. I am new to PL SQL. Please give some suggestions to this. Do i need a cursor or loop for do this

SELECT 
           regexp_substr(profile_value,'\|([^|]+)\|',1,1,NULL,1) 
FROM table1

As a result of my query i am getting only WO_NO=1^

AlexDemo
  • 141
  • 3
  • 14
  • The other parts are also between `| |`. Please be clear about what your requirements are. Also please be clear about what didn't work, and please, do provide the input value as text, so people can easily copy it in order to help you. – GolezTrol Jul 20 '22 at 08:16
  • At first glance, it looks like you could split the string on `|`, and get the even items in the list that gives you. Maybe you can use one of the solutions of [Is there a function to split a string in PL/SQL?](https://stackoverflow.com/questions/3710589/is-there-a-function-to-split-a-string-in-pl-sql) – GolezTrol Jul 20 '22 at 08:17
  • In my query its getting only first value inside the || its correct. But others are not loading. – AlexDemo Jul 20 '22 at 08:29

2 Answers2

2

This is how I understood it.

SQL> with
  2  test (col) as
  3    (select '9D49|WO_NO=1^|WO no: 1;D972|WO_NO=60003^|WO no: 60003;AED1' from dual union all
  4     select '1234|WO_NO=25^|WO no:25;797|WO_NO=26^'                      from dual
  5    ),
  6  temp as
  7    (select regexp_substr(col, '[^|]+', 1, column_value) val,
  8            column_value cv,
  9            col
 10     from test cross join
 11       table(cast(multiset(select level from dual
 12                           connect by level <= regexp_count(col, '\|') + 1
 13                          ) as sys.odcinumberlist))
 14    )
 15  select listagg(val, ' or ') within group (order by cv) result
 16  from temp
 17  where substr(val, 1, 5) = 'WO_NO'
 18  group by col ;

RESULT
--------------------------------------------------------------------------------
WO_NO=25^ or WO_NO=26^
WO_NO=1^ or WO_NO=60003^

SQL>
Littlefoot
  • 131,892
  • 15
  • 35
  • 57
0

Splitting the string into items

Assuming (for now, stay tuned) that Table1 has a single row, you can write a regular expression and use it in a recursive query to split the string in a single select.

level denotes the level of recursion. regexp_substr lets you specify the occurrence in the string. connect by provides the exit condition: taking the next item, until there is none.

select
  level as ItemNr,
  regexp_substr(profile_value, '[^|]+', 1, level) as Item 
from
  Table1
connect by
  regexp_substr(profile_value, '[^|]+', 1, level) is not null

Combining the wanted items into a new string

You could use ListAgg with a case condition, to combine only the items where level is an even number back into a single string, with the string ' or ' as a separator.

select
  listagg(
    case when mod(level, 2) = 0 then
      regexp_substr(profile_value, '[^|]+', 1, level)
    end, ' or ') as Items 
from
  Table1
connect by
  regexp_substr(profile_value, '[^|]+', 1, level) is not null

For multiple rows

The query above doesn't work well by itself if Table1 has multiple rows. It assumes a single input value. Using yet another trick, cross apply, you can make this a subquery that does this transformation for each of the rows of your table.

The query below shows the original profile_value column, and the transformed items for each of the rows in Table1.

select
  t.*, x.*
from
  Table1 t
  cross apply (
    select
      listagg(
        case when mod(level, 2) = 0 then
          regexp_substr(profile_value, '[^|]+', 1, level)
        end, ' or ') as Items
    from 
      dual -- just selecting a single profile_value
    connect by
      regexp_substr(profile_value, '[^|]+', 1, level) is not null
  ) x

In the end this works okay for a not to large set of data, but you're storying structured data into a string, and querying this is not very efficient.

If you need to repeat this query a lot, and the number of rows in Table1 is growing, it's probably better to store it in a more structured way. If this data is coming from an external source, you could dump it in a temporary table, and transform it using the queries of this answer, to write it to a final, better structured table (or tables) for repeated use.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210