Есть ли функция Oracle для определения количества повторяющихся символов - PullRequest
0 голосов
/ 08 мая 2019

Мне нужно проверить количество повторяющихся символов в электронном письме.

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

SELECT 
round(((REGEXP_COUNT(regexp_replace(SUBSTR('999824123@HOTMAIL.COM',1,INSTR('989824123@HOTMAIL.COM', '@', 1)-1), '(.)\1+','&'),'&')+length(SUBSTR('989824123@HOTMAIL.COM',1,INSTR('989824123@HOTMAIL.COM', '@', 1)-1)) - length(regexp_replace(SUBSTR('989824123@HOTMAIL.COM',1,INSTR('989824123@HOTMAIL.COM', '@', 1)-1), '(.)\1+','\1')))* 100)/length(SUBSTR('989824123@HOTMAIL.COM',1,INSTR('989824123@HOTMAIL.COM', '@', 1)-1)),2) AS PORCENTAJE_IGUAL  
FROM DUAL A;

Я ожидаю 60% повторения символа для этого письма 989824123@HOTMAIL.COM.не включая домен.

, пожалуйста, помогите.

PD: извините за плохой английский

1 Ответ

2 голосов
/ 08 мая 2019

Числа 9, 8, 2 повторяются в электронной почте, поэтому у нас есть 6 символов (9, 9, 8, 8, 2, 2), которые повторяются, и 3 уникальных (1, 3, 4).6/9 дает нам 66,67%.Вы можете использовать этот запрос для подсчета:

with 
  t(email) as (select '989824123@hotmail.com' from dual),
  a(email) as (select substr(email, 1,instr(email, '@', 1)-1) from t),
  l as (select substr(email, level, 1) ltr from a connect by level <= length(email))
select sum(case when cnt <> 1 then cnt end) / sum(cnt) 
  from (select ltr, count(1) cnt from l group by ltr)

Я вырезал домен, затем в подзапросе l Я разделил строку на однобуквенные строки, остальное было только для подсчета неуникальных символов и деления на числоиз всех символов.

изменить:

как применить что-то подобное в обновлении или выбрать для крупномасштабной базы данных с большим количеством электронной почты?

Вы можете создать функцию:

create or replace function rpt_similarity(i_email in varchar2) return number is
  v_email varchar2(100);
  v_ret number;
begin 
  v_email := substr(i_email, 1, instr(i_email, '@', 1) - 1);

  with l as (
    select substr(v_email, level, 1) ltr 
      from dual 
      connect by level <= length(v_email)) 
  select sum(case when cnt <> 1 then cnt end) / sum(cnt) 
    into v_ret
    from (select ltr, count(1) cnt from l group by ltr);

  return v_ret;
end;

и использовать ее как здесь:

select rpt_similarity('abxabc@pqr.com') from dual;

или:

select rpt_similarity(email) from your_table;

Также выВы можете использовать вышеуказанное решение в select напрямую, без функции, вот пример:

create table test(id, email) as (  
  select 101, '989824123@hotmail.com'      from dual union all
  select 102, 'hsimpson@gmail.com'         from dual union all
  select 103, 'msimpson@gmail.com'         from dual union all
  select 104, 'bsimpson121314@hotmail.com' from dual union all
  select 105, 'abxabx@hotmail.com'         from dual );

with 
  a(id, email) as (select id, substr(email, 1,instr(email, '@', 1)-1) from test),
  l as (
    select id, email, substr(email, level, 1) ltr from a 
      connect by level <= length(email) 
        and prior id = id and prior sys_guid() is not null) 
select id, email, sum(case when cnt <> 1 then cnt end) / sum(cnt) 
  from (select id, email, ltr, count(1) cnt from l group by id, ltr, email)
  group by id, email;

connect by запросы имеют тенденцию быть медленными для больших наборов данных.Возможно, вы сможете адаптировать свои функции regexp, и это будет быстрее.Я пытался сделать это, но ваш regexp_replace превращается 99 в $ и 999 также в один $.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...