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


with norm as (
    select naimen,
           upper(naimen) as r,
           -- верхний регистр, один пробел, латиница и 0 -> кириллица (для проверки)
           translate(regexp_replace(upper(naimen), '[[:space:]]+', ' '),
                     'ABCEHKMOPTXY0', 'АВСЕНКМОРТХУО') as n,
           -- только для красивого вывода: убираем "метка + длинный номер" и хвост реквизитов
           coalesce(trim(regexp_replace(
               regexp_replace(
                   regexp_replace(naimen,
                       '(БАНК|KPP|КПП|ИНН|[ЛРP]/[СC]|СЧЕТ|СЧ\.?)?[[:space:]]*(N|№)?[[:space:]]*[0-9]{9,}',
                       ' ', 1, 0, 'i'),
                   '[[:space:]]+(' ||
                     '[РP]/[СC]|Ф/АЛ|ДОП\.|НЕВЫЯСНЕНН|ТРАНЗИТНЫЙ' ||
                     '|([[:alpha:]]+[[:space:]]+)?ОСБ' ||
                     '|В[[:space:]]+(ОПЕРУ|ПУШКИНСК)' ||
                     '|Г\.[[:space:]]*[[:alpha:]]' ||
                     '|ОС$|Р/?$' ||
                   ').*$',
                   '', 1, 1, 'i'),
               '[[:space:]]+', ' ')), trim(naimen)) as clean_name
    from sh.uch_vse
    where naimen is not null
),
flag as (
    select naimen, clean_name,
           case when length(trim(naimen)) >= 5 and (
                 -- 1) однозначные формы: в любом месте строки
                 regexp_like(n, '(^|[^А-ЯЁA-Z0-9])(ООО|ОАО|ЗАО|ПАО|НАО|ТОО|ОДО|АООТ|АОЗТ|ФГУП|ГКУП|ГУП|МУП|ГБУ|ГКУ|ГАУ|АНО|НКО|СПК|КФХ|РПО|СНТ|ТСЖ|ЖСК|ЛТД|ЛИМИТЕД)([^А-ЯЁA-Z0-9]|$)')
                 -- 2) короткие неоднозначные: в начале, в конце или между запятыми
              or regexp_like(n, '^[^А-ЯЁA-Z0-9]*(АО|ПК|КБ|АКБ)([^А-ЯЁA-Z0-9]|$)')
              or regexp_like(n, '(^|[^А-ЯЁA-Z0-9])(АО|ПК|КБ|АКБ)[^А-ЯЁA-Z0-9]*$')
              or regexp_like(n, ',[[:space:]]*(АО|ПК|КБ|АКБ)[[:space:]]*,')
                 -- 3) полные и сокращённые названия
              or regexp_like(n, 'ОБЩЕСТВО С ОГРАНИЧЕННОЙ|АКЦИОНЕР|УНИТАРНОЕ ПРЕДПРИЯТИЕ|НЕКОММЕРЧЕСК|НЕКОМ\.')
                 -- 4) иностранные формы
              or regexp_like(r, '(^|[^A-ZА-ЯЁ0-9])(LLC|LTD|JSC|PJSC|INC|GMBH|LIMITED|CORP|SARL|SA|AG|BV|NV|OY)([^A-ZА-ЯЁ0-9]|$)')
              or regexp_like(r, '(^|[^A-ZА-ЯЁ0-9])S\.A\.')
                 -- 5) расширенный блок (удалите, если не нужен): организации без ОПФ по первому слову
              or regexp_like(n, '^[^А-ЯЁA-Z0-9]*(АССОЦИАЦИЯ|АДМИНИСТРАЦИЯ|ТОВАРИЩЕСТВО|КООПЕРАТИВ|КОЛХОЗ|РАЙПО|ФОНД|УПРАВЛЕНИЕ|АДВОКАТСКАЯ|АДВОКАТСКОЕ|ПРЕДСТАВИТЕЛЬСТВО)([^А-ЯЁA-Z0-9]|$)')
                 -- 6) название в кавычках (кроме ИП и физлиц с инициалами)
              or (regexp_like(naimen, '["«»„“”`<>''].{2,}["«»„“”`<>'']')
                  and not regexp_like(n, '(^|[^А-ЯЁA-Z0-9])(ИП|ЧП|ПБОЮЛ|ПРЕДПРИНИМАТЕЛЬ)([^А-ЯЁA-Z0-9]|$)')
                  and not regexp_like(naimen, '^[А-ЯЁ][А-ЯЁа-яё-]+[[:space:]]+[А-ЯЁ]\.', 'c'))
           ) then 1 else 0 end as is_org
    from norm
),
cand as (
    select /*+ materialize */
           clean_name,
           -- 1 = название обрезано полем (длина 50)
           case when length(naimen) >= 50 and clean_name = trim(naimen) then 1 else 0 end as is_cut,
           -- ключ для склейки дублей: только буквы и цифры
           regexp_replace(translate(upper(clean_name), 'ABCEHKMOPTXY0', 'АВСЕНКМОРТХУО'),
                          '[^А-ЯЁA-Z0-9]', '') as k
    from flag
    where is_org = 1
)
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;



with norm as (
    select naimen,
           upper(naimen) as r,
           translate(regexp_replace(upper(naimen), '[[:space:]]+', ' '),
                     'ABCEHKMOPTXY0', 'АВСЕНКМОРТХУО') as n
    from sh.uch_vse
    where naimen is not null
),
flag as (
    select naimen,
           case when length(trim(naimen)) >= 5 and (
                 regexp_like(n, '(^|[^А-ЯЁA-Z0-9])(ООО|ОАО|ЗАО|ПАО|НАО|ТОО|ОДО|АООТ|АОЗТ|ФГУП|ГКУП|ГУП|МУП|ГБУ|ГКУ|ГАУ|АНО|НКО|СПК|КФХ|РПО|СНТ|ТСЖ|ЖСК|ЛТД|ЛИМИТЕД)([^А-ЯЁA-Z0-9]|$)')
              or regexp_like(n, '^[^А-ЯЁA-Z0-9]*(АО|ПК|КБ|АКБ)([^А-ЯЁA-Z0-9]|$)')
              or regexp_like(n, '(^|[^А-ЯЁA-Z0-9])(АО|ПК|КБ|АКБ)[^А-ЯЁA-Z0-9]*$')
              or regexp_like(n, ',[[:space:]]*(АО|ПК|КБ|АКБ)[[:space:]]*,')
              or regexp_like(n, 'ОБЩЕСТВО С ОГРАНИЧЕННОЙ|АКЦИОНЕР|УНИТАРНОЕ ПРЕДПРИЯТИЕ|НЕКОММЕРЧЕСК|НЕКОМ\.')
              or regexp_like(r, '(^|[^A-ZА-ЯЁ0-9])(LLC|LTD|JSC|PJSC|INC|GMBH|LIMITED|CORP|SARL|SA|AG|BV|NV|OY)([^A-ZА-ЯЁ0-9]|$)')
              or regexp_like(r, '(^|[^A-ZА-ЯЁ0-9])S\.A\.')
              or regexp_like(n, '^[^А-ЯЁA-Z0-9]*(АССОЦИАЦИЯ|АДМИНИСТРАЦИЯ|ТОВАРИЩЕСТВО|КООПЕРАТИВ|КОЛХОЗ|РАЙПО|ФОНД|УПРАВЛЕНИЕ|АДВОКАТСКАЯ|АДВОКАТСКОЕ|ПРЕДСТАВИТЕЛЬСТВО)([^А-ЯЁA-Z0-9]|$)')
              or (regexp_like(naimen, '["«»„“”`<>''].{2,}["«»„“”`<>'']')
                  and not regexp_like(n, '(^|[^А-ЯЁA-Z0-9])(ИП|ЧП|ПБОЮЛ|ПРЕДПРИНИМАТЕЛЬ)([^А-ЯЁA-Z0-9]|$)')
                  and not regexp_like(naimen, '^[А-ЯЁ][А-ЯЁа-яё-]+[[:space:]]+[А-ЯЁ]\.', 'c'))
           ) then 1 else 0 end as is_org
    from norm
)
select distinct naimen as "Наименование"
from flag
where is_org = 0
order by 1;




create table spr_gorod as
with src as (
    select translate(upper(trim(naimen)), 'ABCEHKMOPTXY', 'АВСЕНКМОРТХУ') as u,
           length(naimen) as len
    from sh.uch_vse
    where naimen is not null
),
ext as (
    select u, len,
           regexp_substr(u,
             '(^|[^А-ЯЁ])(Г|ГОР|ГОРОД|ГОРОДА)[. ]+((НИЖНИЙ|НОВЫЙ|НОВАЯ|СТАРЫЙ|СТАРАЯ|ВЕЛИКИЙ|ВЕЛИКИЕ|НАБЕРЕЖНЫЕ|УСТЬ|ЙОШКАР)[ -][А-ЯЁ]{2,}|[А-ЯЁ]{2,}(-[А-ЯЁ]{1,}){0,3})',
             1, 1, 'c', 3) as city_raw,
           regexp_substr(u,
             '(^|[^А-ЯЁ])(Г|ГОР|ГОРОД|ГОРОДА)[. ]+((НИЖНИЙ|НОВЫЙ|НОВАЯ|СТАРЫЙ|СТАРАЯ|ВЕЛИКИЙ|ВЕЛИКИЕ|НАБЕРЕЖНЫЕ|УСТЬ|ЙОШКАР)[ -][А-ЯЁ]{2,}|[А-ЯЁ]{2,}(-[А-ЯЁ]{1,}){0,3})',
             1, 1, 'c', 0) as m
    from src
),
clean as (
    select regexp_replace(replace(city_raw, 'Ё', 'Е'), '[[:space:]]+', ' ') as city
    from ext
    where city_raw is not null
      -- выбрасываем город, если строка обрезана полем прямо на нём (Г.МОС, Г ДУБ)
      and not (len >= 50 and instr(u, m) + length(m) - 1 >= length(u))
),
uniq as (
    select city
    from clean
    where length(city) >= 3
    group by city
    -- having count(*) >= 2   -- раскомментируйте, чтобы убрать редкий мусор
)
select row_number() over (order by city) as id,
       city as name
from uniq;