Загрузка данных


with src as (
    select naimen,
           -- обрезаем хвост из банковских реквизитов
           regexp_replace(
               trim(naimen),
               '[[:space:]]+(' ||
                 '[РP]/[СC]' ||
                 '|([[:alpha:]]+[[:space:]]+)?ОСБ' ||
                 '|В[[:space:]]+(ОПЕРУ|ПУШКИНСК)' ||
                 '|ТРАНЗИТНЫЙ|ДОП\.|НЕВЫЯСНЕНН' ||
                 '|Ф/АЛ|ФИЛИАЛ|КАШИРСКИЙ' ||
                 '|Г\.[[:space:]]*[[:alpha:]]' ||
               ').*$',
               '', 1, 1, 'i'
           ) as clean_name
    from sh.uch_vse
    where naimen is not null
      and length(naimen) between 5 and 300
),
norm as (
    select clean_name,
           -- 1 = название обрезано полем (длина 50) и хвост не вырезался
           case when length(naimen) >= 50
                 and clean_name = trim(naimen) then 1 else 0 end as is_cut,
           upper(trim(clean_name)) as r,  -- для LLC, LTD и т.п.
           -- верхний регистр, схлопнутые пробелы, латиница и 0 -> кириллица
           translate(
               regexp_replace(upper(trim(clean_name)), '[[:space:]]+', ' '),
               'ABCEHKMOPTXY0',
               'АВСЕНКМОРТХУО'
           ) as n
    from src
),
cand as (
    select /*+ materialize */
           clean_name,
           is_cut,
           -- ключ для склейки дублей: только буквы и цифры
           regexp_replace(n, '[^А-ЯЁA-Z0-9]', '') as k
    from norm
    where (
            -- аббревиатуры
            regexp_like(n,
              '^(ООО|ОАО|ЗАО|ПАО|АО|НАО|ТОО|НКО|ФГУП|МУП|ГУП|ГБУ|ГКУ|ГАУ|АНО|ПК|СПК|КФХ|РПО|СНТ|ТСЖ|ЖСК|АКБ|КБ)([[:space:]"«„''‘’“”`<]|$)')
            -- полные названия
         or regexp_like(n,
              '^(ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ|(ПУБЛИЧНОЕ |ЗАКРЫТОЕ |ОТКРЫТОЕ )?АКЦИОНЕРНОЕ ОБЩЕСТВО)([[:space:]"«„''‘’“”`<]|$)')
            -- иностранные формы
         or regexp_like(r,
              '^(LLC|LTD|JSC|PJSC|INC|GMBH)([[:space:]"«„''‘’“”`<]|$)')
          )
      -- физлица с инициалами
      and not regexp_like(clean_name, '^[А-ЯЁ][А-ЯЁа-яё-]+[[:space:]]+[А-ЯЁ]\.', 'c')
      -- мусор с длинными номерами счетов
      and not regexp_like(clean_name, '[0-9]{9,}')
      -- банки (уберите строку, если банки нужны)
      and not regexp_like(n, '(^|[[:space:]"«])(БАНК|АКБ|КБ)([[:space:]"»]|$)')
)
select min(c.clean_name) as "Наименование"
from cand c
where c.is_cut = 0
   or not exists (
        select 1
        from cand x
        where x.k like c.k || '_%'
      )
group by c.k
order by 1;