Вы можете попытаться использовать regexp_replace
, чтобы пойти в правильном направлении:
create table tq84_products (
name varchar2(50),
price varchar2( 5)
);
Три продукта:
, из которых ABCD имеет две записи с одинаковой ценой, а все остальные имеют другую цену.
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');
Оператор выбора с стоп-словами для удаления слов, которые обычно встречаются в названиях продуктов.
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;
Затем выбирается
$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
Таким образом, abcd не возвращается, в то время как остальные.