Home » SQL & PL/SQL » SQL & PL/SQL » Pattern Matching for Multivalue (Oracle 11g R2)
Pattern Matching for Multivalue [message #650776] Tue, 03 May 2016 08:51 Go to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

Gurus,

I have a scenario where i have to do a pattern matching for a string value.
This is my table

create table mydata 
(country varchar2(100));

insert into mydata values ('japan,china,russia,italy');

commit;


now i want to write a query for pattern matching where user can search any string in any order.
Something like japan and russia together or russia and china and japan together or just japan.
Any string in any order.

Is that possible ?

Javed A. Khan
Re: Pattern Matching for Multivalue [message #650777 is a reply to message #650776] Tue, 03 May 2016 09:17 Go to previous messageGo to next message
Michel Cadot
Messages: 68644
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Quote:
Something like japan and russia together or russia and china and japan together or just japan.


What do you mean EXACTLY?
What is the input?
Post an example.

Quote:
Is that possible ?


Yes.

Note that multi-valued field is NOT relational as it breaks the FIRST normal form (read Normalization) and then leads to this kind of problem when the language you have to use is a relational one.

Re: Pattern Matching for Multivalue [message #650778 is a reply to message #650777] Tue, 03 May 2016 09:38 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
NEVER store more than 1 value in a (single) column!
Re: Pattern Matching for Multivalue [message #650781 is a reply to message #650778] Tue, 03 May 2016 11:08 Go to previous messageGo to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

Sorry if i was not clear .. a query i need which can take input for any part of string existing in the column which is comma seperated string. A query passed with parameter like this

'japan,russia' shall give string back because japan and russia exist in the string no matter order or without order.

Javed
Re: Pattern Matching for Multivalue [message #650782 is a reply to message #650778] Tue, 03 May 2016 11:09 Go to previous messageGo to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

I completely agree , but its a requirement because the parent system provides data in this format to slave system [Which is me on oracle].
Re: Pattern Matching for Multivalue [message #650783 is a reply to message #650782] Tue, 03 May 2016 11:22 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
javed.khan wrote on Tue, 03 May 2016 09:09
I completely agree , but its a requirement because the parent system provides data in this format to slave system [Which is me on oracle].


So why can't/don't/won't you normalize the data after it is deposited into Oracle?
Re: Pattern Matching for Multivalue [message #650784 is a reply to message #650781] Tue, 03 May 2016 11:24 Go to previous messageGo to next message
Michel Cadot
Messages: 68644
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

You can split the input and data into element and count them.
SQL> with
  2    input as (select '&input' input from dual),
  3    in_split as (
  4      select distinct regexp_substr(input,'[^,]+',1,level) input
  5      from input
  6      connect by level <= regexp_count(input,',')+1
  7    ),
  8    in_count as (select count(*) in_nb from in_split),
  9    data_split as (
 10      select distinct country, regexp_substr(country,'[^,]+',1,column_value) co
 11      from mydata,
 12           table(cast(multiset(select level from dual
 13                               connect by level <= regexp_count(country,',')+1)
 14                      as sys.odcivarchar2list))
 15    )
 16  select country
 17  from data_split, in_split
 18  where co = input
 19  group by country
 20  having count(*) = (select in_nb from in_count)
 21  /
Enter value for input: japan,russia
COUNTRY
------------------------------------------------------------------------------------
japan,china,russia,italy

1 row selected.

SQL> /
Enter value for input: italy,japan
COUNTRY
-----------------------------------
japan,china,russia,italy

1 row selected.

SQL> /
Enter value for input: france,china

no rows selected

Re: Pattern Matching for Multivalue [message #650785 is a reply to message #650784] Tue, 03 May 2016 13:08 Go to previous messageGo to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

Wow.... That's exactly what i wanted to know. I could not do this by myself i swear. Thanks for enlightenment dear gurus.
Re: Pattern Matching for Multivalue [message #650786 is a reply to message #650783] Tue, 03 May 2016 13:12 Go to previous messageGo to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

Yes sure we should do. The thing is its Taleo pushing data to my other table where i am helpless to do normalization and this was reported this way from years . Now suddenly user wants a pattern match search. Anyway i will take this point and try to transpose the data in table format.

Thanks for your valuable time and effort.

Javed
Re: Pattern Matching for Multivalue [message #650787 is a reply to message #650786] Tue, 03 May 2016 21:09 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
Another option would be creating an Oracle Text index and querying using CONTAINS, as demonstrated below.

SCOTT@orcl> create table mydata (country varchar2(100));

Table created.

SCOTT@orcl> insert all
  2  into mydata values ('japan,china,russia,italy')
  3  into mydata values ('russia,china,japan,italy')
  4  into mydata values ('russia,china,italy')
  5  into mydata values ('china,japan,italy')
  6  select * from dual;

4 rows created.

SCOTT@orcl> create index myindex on mydata (country) indextype is ctxsys.context parameters ('sync (on commit)');

Index created.

SCOTT@orcl> select * from mydata where contains (country, replace ('japan,russia', ',', ' and ')) > 0;

COUNTRY
--------------------------------------------------------------------------------
japan,china,russia,italy
russia,china,japan,italy

2 rows selected.


Re: Pattern Matching for Multivalue [message #651584 is a reply to message #650787] Fri, 20 May 2016 07:33 Go to previous messageGo to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

Thanks Barbara
Re: Pattern Matching for Multivalue [message #651591 is a reply to message #651584] Fri, 20 May 2016 09:48 Go to previous message
Bill B
Messages: 1971
Registered: December 2004
Senior Member
You can do it easly with the following code

CREATE OR REPLACE FORCE VIEW Mydata_v
(
   Country,
   Id_num
)
AS
   SELECT EXTRACT (VALUE (D), '//row/text()').Getstringval () AS Country,
          Id_num
     FROM (SELECT Id_num,
                  Xmltype (
                        '<rows><row>'
                     || REPLACE (Country, ',', '</row><row>')
                     || '</row></rows>')
                     AS Xmlval
             FROM Mydata) X,
          TABLE (XMLSEQUENCE (EXTRACT (X.Xmlval, '/rows/row'))) D;

>desc mydata
 Name                                      Null?    Type
 ----------------------------------------- -------- -------------------
 COUNTRY                                            VARCHAR2(100)
 ID_NUM                                             NUMBER

>desc mydata_v
 Name                                      Null?    Type
 ----------------------------------------- -------- -------------------
 COUNTRY                                            VARCHAR2(4000)
 ID_NUM                                             NUMBER

select id_num
from mydata_v
where country in ('japan','russia')
group by id_num
having count(*) = 2;

    ID_NUM
----------
         1
         2

> select * from mydata;
raydw@rayora1>/

COUNTRY                                      ID_NUM
---------------------------------------- ----------
japan,china,russia,italy                          1
russia,china,japan,italy                          2
russia,china,italy                                3
china,japan,italy                                 4


Previous Topic: sysdate in the pivot in clause
Next Topic: Display the columns of a table into rows delimited by comma
Goto Forum:
  


Current Time: Wed Apr 24 07:22:03 CDT 2024