Объединить похожие строки на основе имени и считать в Oracle SQL или PL / SQL - PullRequest
0 голосов
/ 26 февраля 2020

У нас есть данные, как показано ниже

CompanyID   CompanyName
1000        Decisive Data
1001        Decisive Data, Inc.
1002        Decisive Data Inc.
1003        Thomson ABC Data 
1004        Thomson ABC Data Pvt Ltd
1005        Susheel Solutions R K
1006        Susheel R K Sol
1007        R K Susheel Data Solutions
1008        GMR Infra
1009        GMR Infra Projects
1010        GMR Infrastructure Projects Ltd

Ожидаемый результат запроса:

CompanyName                    Count
Decisive Data, Inc.                3
Thomson ABC Data Pvt Ltd           2
R K Susheel Data Solutions         3
GMR Infrastructure Projects Ltd    3

Возможно ли использовать некоторые совпадения и слияния логи c и показать ожидаемый результат.

Ответы [ 3 ]

0 голосов
/ 26 февраля 2020

Это трудно сделать в sql. Но я предложу подход. Разделите имена на токены по пробелам, а затем посмотрите, сколько токенов совпадают между именами компаний.

Как только вы определите «порог» числа, вам понадобится какое-то ручное вмешательство, чтобы решить, какие из них являются хорошими совпадениями.

После этого вы получите представление о том, сколько из них, вероятно, совпадают. Это должно помочь в агрегации логи c.

Например: в последнем запросе поля (cnt_token) и (cnt_matching_tokens) сообщают, что «Решающие данные» имеют 2 из 2 совпадений с «Решающими данными в c.»

X       Y               B_Y                 TOKEN_VAL   CNT_TOKENS  CNT_OF_MATCHING_TOKENS
1000    Decisive Data   Decisive Data Inc.  Decisive    2           2
1000    Decisive Data   Decisive Data Inc.  Data        2           2


create table t(x int, y varchar2(500));

insert 
  into t
select 1000 ,'Decisive Data'                      from dual union all                  
select 1001 ,'Decisive Data, Inc.'                from dual union all
select 1002 ,'Decisive Data Inc.'                 from dual union all
select 1003 ,'Thomson ABC Data '                  from dual union all
select 1004 ,'Thomson ABC Data Pvt Ltd'           from dual union all
select 1005 ,'Susheel Solutions R K'              from dual union all
select 1006 ,'Susheel R K Sol'                    from dual union all
select 1007 ,'R K Susheel Data Solutions'         from dual union all
select 1008 ,'GMR Infra'                          from dual union all
select 1009 ,'GMR Infra Projects'                 from dual union all
select 1010 ,'GMR Infrastructure Projects Ltd'    from dual;

commit;

--Example using jaro_winkler_similarity of string.
select * from(
select a.x,a.y as a_y,b.x as b_x,b.y,round(utl_match.jaro_winkler_similarity(a.y,b.y),2) as similar_dist
  from t a
  join t b
    on a.x <> b.x
)m
where m.similar_dist>=80

--comparision based on tokens of the name
with data /*This would split the name into rows based on <space>*/
  as (select distinct x,y, replace(trim(regexp_substr(y,'[^ ]+', 1, level) ),',','') as token_val, level
        from t  
      connect by regexp_substr(y, '[^ ]+', 1, level) is not null
      )
   ,data2
      as(
        select x,count(token_val) as cnt_tokens
          from data
          group by x
         )
select * from (         
select a.x,a.y,b.y as b_y,a.token_val
       ,a1.cnt_tokens
       ,count(*) over(partition by a.y,b.y) as cnt_of_matching_tokens
  from data a
  join data2 a1
    on a.x=a1.x
left join data b
     on a.token_val=b.token_val
     and a.x <> b.x
)y
0 голосов
/ 26 февраля 2020

На мой взгляд, это трудно сделать на Oracle Вы можете go на другие языки, например Java или в моем случае Python.

Результат не дает права на все ваши дела, но хороший подход. Позвольте мне высказать вам свое мнение, и, если вы заинтересованы, можете указать целое число в вашей работе:

Прежде всего установите пакет difflibhelper

pip3 install difflibhelper

после того, как вы получите ваш примеры:

открыть python скрипт или приглашение ...

Вот мой код для создания некоторого соотношения:

from difflib import SequenceMatcher

def s_ratio(a, b):
  return SequenceMatcher(None, a, b).ratio()

lista_1 = [
  'Decisive Data',
    ...
  'GMR Infrastructure Projects Ltd'
]
lista_2 = [data.split() for data in lista_1]
for data in lista_2:
  data.sort()
lista_3 = []
[lista_3.append(' '.join(data)) for data in lista_2]

print(s_ratio(lista_3[0], lista[1])) -> Result **0.8125** # it means data is compatible

Когда вы присоединяетесь ко всем данным, вы нужно знать кое-что, во-первых, если ваши утверждения упорядочены, и когда вы сравниваете, вы продолжаете или сравниваете 1 x 1.

Также вам нужно определить коэффициент , чтобы найти прозрачность .

И, наконец, вам нужно записать данные в файл (это очень просто) для разбора данных на SQL.

0 голосов
/ 26 февраля 2020

Следующее довольно дорого, но это должно работать на ваших конкретных данных. Чтобы получить «родительское имя»:

select t.companyName, min(tp.companyname) as parent_companyname
from t join
     t tp
     on t.companyname like tp.companyname || '%';

Затем агрегируйте:

select parent_companyname, count(*)
from (select t.companyName, min(tp.companyname) as parent_companyname
      from t join
           t tp
           on t.companyname like tp.companyname || '%'
     ) t
group by parent_companyname;

Примечания:

  • Это НЕ будет очень хорошо масштабироваться.
  • Это сильно зависит от данных, но это должно работать на вашем примере.
  • Исправление имен является трудной проблемой. Мой совет - поместить имена в электронную таблицу и вручную добавить каноническое имя.
...