Загрузка данных
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;