2017-01-12 2 views
0

Мне нужны ваши предложения/предложения для следующей задачи. У меня есть следующая таблица:Oracle SQL Повторяющиеся слова в строке

ID  ID_NAME        
------ --------------------------------- 
1  TOM HANKS TOM JR      
2  PETER PATROL PETER JOHN PETER  
3  SAM LIVING       
4  JOHNSON & JOHNSON INC    
5  DUHGT LLC        
6  THE POST OF THE OFFICE    
7  TURNING REP WEST      
8  GEORGE JOHN       

Мне нужен SQL-запрос, чтобы найти повторяющееся слово для каждого идентификатора. если он существует, мне нужно получить счет повторного слова. Например, в ID 2 слово PETER повторялось 3 раза, а в ID 1 слово TOM повторялось дважды. так что мне нужно на выходе что-то вроде этого:

ID  ID_NAME        COUNT 
------ --------------------------------- -------- 
1  TOM HANKS TOM JR     2 
2  PETER PATROL PETER JOHN PETER  3 
3  SAM LIVING       0 
4  JOHNSON & JOHNSON INC    2 
5  DUHGT LLC       0  
6  THE POST OF THE OFFICE    2 
7  TURNING REP WEST     0 
8  GEORGE JOHN       0 

Просто FYI, таблица имеет 560k строк

Я пробовал ниже, и это не сработало, и он буквально ищет для каждого слова.

SELECT RESULT, COUNT(*) 
    FROM (SELECT 
      REGEXP_SUBSTR(COL_NAME, '[^ ]+', 1, COLUMN_VALUE) RESULT 
      FROM TABLE_NAME T , 
       TABLE(CAST(MULTISET(SELECT DISTINCT LEVEL 
            FROM TABLE_NAME X 
       CONNECT BY LEVEL <= LENGTH(X.COL_NAME) - LENGTH(REPLACE(X.COL_NAME, ' ', '')) + 1 
           ) AS SYS.ODCINUMBERLIST)) T1 
     ) 
    WHERE RESULT IS NOT NULL 
    GROUP BY RESULT 
    ORDER BY 1; 

Пожалуйста, дайте мне знать ваши данные.

+0

Привет Кумар, - получить ваши таблицы и форматировать код, что вы сделали было отлично, но это еще один шаг - вам нужно для выбора текста и нажмите Ctrl-K или маленькую иконку {} вверху. Пожалуйста, помните о будущих публикациях. – mathguy

+0

Посмотрите на функцию REGEXP_COUNT. – OldProgrammer

+2

Что делать, если есть несколько повторений? – mathguy

ответ

0

Следующее решение найти первое повторение слова и в следующем шаге найти количество повторений. Редактировать только сейчас, чтобы исправить дополнительные подсловной выводы

with s (ID, ID_NAME) as (
select 1, 'TOM HANKS TOM JR' from dual union all  
select 10, 'TO TOM TOM TOM TOM TO TO TO STOM HANKS TOM TOMMY' from dual union all  
select 2, 'PETER PATROL PETER JOHN PETER' from dual union all 
select 3, 'SAM LIVING' from dual union all 
select 4, 'qwe JOHNSON & JOHNSON INC' from dual union all 
select 5, 'DUHGT LLC' from dual union all 
select 6, 'THE POST OF THE OFFICE ' from dual union all 
select 7, 'TURNING REP WEST ' from dual union all 
select 8, 'GEORGE JOHN ' from dual) 
select id, 
     case when r1 = 0 then 0 
      else regexp_count(id_name, r3) 
       - regexp_count(id_name, r3||'\w+') -- exlude word with tail 
       - regexp_count(id_name, '\w+'||r3) -- exclude words with head 
       + regexp_count(id_name, '\w+'||r3||'\w+') -- double calc with head and tail 
     end as rep_count 
     from (
select 
s.*, 
regexp_instr(s.id_name, '(^|\s)(\w+)(\s|$)(.*(\2))+') as r1 , 
regexp_replace(s.id_name, '.*?(^|\s)(\w+)(\s)(.*(\s)\2(\s|$))+.*$', '\2') as r3 
from s); 

результат

ID REP_COUNT 
---------- ---------- 
    1  2 
    10  4 
    2  3 
    3  0 
    4  2 
    5  0 
    6  2 
    7  0 
    8  0 
1

В нижеследующем запросе подсчитываются повторяющиеся слова и возвращает наивысший счетчик (если слово появляется три раза, а другое появляется дважды, результатом будет число 3). Он обрабатывает JOHN как отличное от John (если капитализация не должна считаться «разной», тогда оберните входящие строки в пределах UPPER(...)). Он рассматривает пространство как разделитель слов; если что-то еще, например, тире, также рассматривается как разделитель, добавьте в шаблон поиска REGEXP. Удостоверьтесь, что вы поместили штрих в конце списка символов совпадающего квадратного квадрата и т. Д. - обычные «трюки» для сопоставления списков символов. В более общем плане, при необходимости адаптируйте.

Запрос сначала разбивает каждую строку ввода на отдельные слова и подсчитывает, сколько раз каждое слово появляется. Для count мне нужны только слова («токены») в предложении GROUP BY, мне не нужно на самом деле SELECT их, поэтому самый внутренний запрос может выглядеть нечетным, если вы не предупреждены. (Теперь вы!)

Также кажется, что вы хотите показать null, а не 1, если повторных слов нет, поэтому я написал запрос, чтобы это учесть. (. Не знаю, почему 1 не было ОК)

with 
    test_data (id, id_name) as (
     select 1, 'TOM HANKS TOM JR'    from dual union all 
     select 2, 'PETER PATROL PETER JOHN PETER' from dual union all 
     select 3, 'SAM LIVING'     from dual union all 
     select 4, 'JOHNSON & JOHNSON INC'   from dual union all 
     select 5, 'DUHGT LLC'      from dual union all 
     select 6, 'THE POST OF THE OFFICE'  from dual union all 
     select 7, 'TURNING REP WEST'    from dual union all 
     select 8, 'GEORGE JOHN'     from dual 
    ) 
-- end of test data; SQL query begins below this line 
select id, id_name, case when max(cnt) >= 2 then max(cnt) end as max_count 
from (
     select id, id_name, count(*) as cnt 
     from test_data 
     connect by level <= 1 + regexp_count(id_name, ' ') 
       and prior id = id 
       and prior sys_guid() is not null 
       group by id, id_name, regexp_substr(id_name, '[^ ]+', 1, level) 
    ) 
group by id, id_name 
order by id  -- if needed 
; 

Выход:

ID ID_NAME      MAX_COUNT 
-- ----------------------------- ---------- 
1 TOM HANKS TOM JR      2 
2 PETER PATROL PETER JOHN PETER   3 
3 SAM LIVING 
4 JOHNSON & JOHNSON INC     2 
5 DUHGT LLC 
6 THE POST OF THE OFFICE     2 
7 TURNING REP WEST 
8 GEORGE JOHN 

8 rows selected. 

EDIT:

Если вам нужно только найти возвращения, где столбец строка имеет по крайней мере одно повторяющееся слово, и вам все равно, что самое высокое «количество повторных слов» или сколько слов повторяется, решение проще и эффективнее; вам не нужно разделить входную строку на компонентные слова и подсчитать их.

(ОП указывается в комментариях, после долгого диалога, что это будет достаточно.)

В растворе «шаблон матча» в regexp_like поисках строки букв, предшествуют либо в начале строка или пробел или тире и заканчивается пробелом, запятой, периодом, вопросительным знаком, восклицательным знаком или тире. Оба «маркера» для начала и конца слова могут быть изменены по мере необходимости. Удостоверьтесь, что тире является либо первым, либо последним символом в [...], где бы то ни было, это имеет особое значение.

Затем он ищет повторение слова.Вот что делает \2 в шаблоне матча. Это 2, а не 1, потому что «слово» находится во второй паре круглых скобок; Мне нужна первая пара для чередования, или начало строки OR (пробел или тире).

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

with 
    test_data (id, id_name) as (
     select 1, 'TOM HANKS TOM-ALAN'   from dual union all 
     select 2, 'PETER PATROL PETER JOHN PETER' from dual union all 
     select 3, 'SAM LIVING'     from dual union all 
     select 4, 'JOHNSON & JOHNSON INC'   from dual union all 
     select 5, 'DUHGT LLC'      from dual union all 
     select 6, 'THE POST OF THE OFFICE'  from dual union all 
     select 7, 'TURNING REP WEST'    from dual union all 
     select 8, 'GEORGE JOHN-JOHN'    from dual 
    ) 
-- end of test data; SQL query begins below this line 
select id, id_name 
from test_data 
where regexp_like(id_name, '(^|[ -])([[:alpha:]]+)[ ,.?!-].*\2') 
order by id -- if needed 
; 

ID ID_NAME 
-- ----------------------------- 
1 TOM HANKS TOM-ALAN 
2 PETER PATROL PETER JOHN PETER 
4 JOHNSON & JOHNSON INC 
6 THE POST OF THE OFFICE 
8 GEORGE JOHN-JOHN 
+0

Спасибо. Но у меня есть 560K строк в таблице, которые нужно проверить. так что мне нужно подготовить 560K союз SQL со всеми значениями? –

+0

Нет, нет. Где бы я ни находился в моем решении (это все ниже строки с комментариями), у меня есть имя таблицы или имя столбца, мой запрос относится к таблице «test_data» «Я создал в предложении WITH. Замените те, у которых есть фактические имена таблиц и столбцов, вместо ссылки на таблицу 'test_data'. – mathguy

+0

@mathguy, можете ли вы попытаться сделать 'MAX_COUNT' равным нулю, если в столбце' ID_NAME' нет дубликатов? –

Смежные вопросы