2011-01-27 3 views
0

J'ai une très grande table (plus de 1 million de lignes), Ces lignes ont le nom du produit et le prix de différentes sources.Correspondance partielle dans Oracle Database

Il existe de nombreux produits qui portent le même nom mais dont le prix est différent.

Voici le problème,

Nous avons même produit plusieurs fois dans la ligne mais leur nom ne sera pas même par exemple

Row Product name    price 
----- ----------------------- ---- 
Row 1 : XYZ - size information $a 
Row 2. XYZ -Brand information $b 
Row 3. xyz      $c 

Je veux obtenir tous les produits qui dérogent prix. Si le nom est même dans la ligne alors je peux facilement aller pour soi joindre comme Table1.Product_Name = Table1.Product_name et Table1.Price! = Table2.Price

Mais cela ne fonctionnera pas dans ce cas :(

Can une proposer une solution pour elle

Répondre

3

Vous pouvez essayer d'utiliser regexp_replace pour aller dans la bonne direction:

create table tq84_products (
    name varchar2(50), 
    price varchar2(5) 
); 

Trois produits:

  • xyz
  • ABCD
  • EFGHI

dont ABCD a deux enregistrements avec le même prix et tous les autres ont un prix différent.

insert into tq84_products values (' XYZ - size information', '$a'); 
insert into tq84_products values ('XYZ - brand information', '$b'); 
insert into tq84_products values ('xyz'     , '$c'); 

insert into tq84_products values ('Product ABCD'   , '$d'); 
insert into tq84_products values ('Abcd is the best'  , '$d'); 

insert into tq84_products values ('efghi is cheap'   , '$f'); 
insert into tq84_products values ('no, efghi is expensive' , '$g'); 

L'instruction select avec mots d'arrêt pour supprimer des mots qui sont généralement trouvés dans les noms de produits.

with split_into_words as (
     select 
     name, 
     price, 
     upper (
     regexp_replace(name, 
          '\W*' || 
         '(\w+)?\W?+' || 
         '(\w+)?\W?+' || 
         '(\w+)?\W?+' || 
         '(\w+)?\W?+' || 
         '(\w+)?\W?+' || 
         '(\w+)?\W?+' || 
         '(\w+)?\W?+' || 
         '(\w+)?\W?+' || 
         '(\w+)?'  || 
         '.*', 
         '\' || submatch.counter 
        ) 
     )       word 
     from 
      tq84_products, 
      (select 
       rownum counter 
      from 
       dual 
      connect by 
       level < 10 
      ) submatch 
), 
    stop_words as (
    select 'IS'   word from dual union all 
    select 'BRAND'  word from dual union all 
    select 'INFORMATION' word from dual 
) 
    select 
    w1.price, 
    w2.price, 
    w1.name, 
    w2.name 
-- substr(w1.word, 1, 30)    common_word, 
-- count(*) over (partition by w1.name) cnt 
    from 
    split_into_words w1, 
    split_into_words w2 
    where 
    w1.word = w2.word and 
    w1.name < w2.name and 
    w1.word is not null and 
    w2.word is not null and 
    w1.word not in (select word from stop_words) and 
    w2.word not in (select word from stop_words) and 
    w1.price != w2.price; 

Cette sélectionne ensuite

$a $b  XYZ - size information       XYZ - brand information 
$b $c XYZ - brand information       xyz 
$a $c  XYZ - size information       xyz 
$f $g efghi is cheap          no, efghi is expensive 

Ainsi, ABCD est pas retourné alors que les autres sont.

+0

Je vais essayer ça. – onsy

+0

Ceci est utile seulement une préoccupation est 'Les mots d'arrêt ne sont pas fixés dans mon cas.' – onsy

Questions connexes