Загрузка данных
. МАКАРЕНКО АЛЕКСЕЙ АЛЕКСЕЕВИЧ НОТАРИУС Г.МОСКВЫ
WITH
stop_w AS (
SELECT REPLACE(REPLACE(q'[ООО,ОАО,ПАО,ЗАО,АО,ОДО,ОСБ,АКБ,КБ,ГУП,ГУПУ,МУП,ФГУП,ФУ,КОРПОРЕЙШН,СОФТ,ИНТЕРНЭШНЛ,МЭП,ХОЗ-ВО,РУФПС,
ПАЛАТА,ОАНО,УЗЕЛ,КОНЦЕРН,ФОНД,БАНК,КОМПАНИЯ,ПРЕДПРИЯТИЕ,ОБЩЕСТВО,СОЮЗ,ВКЛАДЫ,ГРАЖДАН,КОРПОРАЦИЯ,КОРПОРАЦИИ,
ИНСТИТУТ,ПОДРАЗДЕЛЕНИЕ,СЕТИ,ОТД,МЕДИА,КЛУБ,РАЙПО,УСИБ,ОБЩ-ВО,ЕДИНЕНИЕ,СКАНСКА,ОТДЕЛЕНИЕ,ПОСОЛЬСТВО,ПОДВОРЬЕ,
КОНСУЛЬТАЦИЯ,СОВЕТ,ФИЛИАЛ,ЗАВОД,ОБЛПО,ГРУППА,СЧЕТ,РЕДАКЦИЯ,НПФ,ГП,ЧАСТЬ,РПЦ,ПИИ,ЭКСПЕДИЦИЯ,ГОСТИНИЦА,СНГ,
ПАРТИЯ,БЮРО,ЕДИНИЦА,Ф-Л,ТУРИЗМ,УМП,ДОМ,ТОВАРИЩЕСТВО,ФИН,РУПС,МЭИ,ЖСК,ТСЖ,ВДПО,ГМБХ,МИНФИН,МИНИФИН,РОС-Я,АРТЕЛЬ,ТЭЛСИС, ОПХ,ТЕПЛОВЫХ,
СИСТЕМС,СОДЕКСО,З-Д,Ф-Т,ЛИМИТЕД,ГОС,НЕФТЕБАЗА,ВЭИ,КОМБИНАТ,КООПЕРАТИВ,ДИСТАНЦИЯ,ЖИЛЬЕ,ЛИЦО,ЛИЦА,ХОЗЯЙСТВО,АВТОШКОЛА, ФРИДАС,
УЧАСТОК,ШАХТА,ИСТЕРН,ПССП,ОТКРЫТОЕ,ЗАКРЫТОЕ,АКЦИОНЕРНОЕ,ГОРОД,ГОРОДА,ПО,МФ,ДОАО,ГПИНЖ,ПСЖА,ФИО]', CHR(10)), CHR(13)) AS s
FROM DUAL
),
stop_p AS (
SELECT REPLACE(REPLACE(q'[НЕВЫЯСНЕ,ПАРТНЕР,ОБЪЕДИ,ОБЪЕД-,АДМИНИСТРА,УПРАВЛЕНИ,ДЕПАРТАМЕНТ,КОМИТЕТ,МИНИСТЕРСТВ,ПОЛИТИЧ,ПРЕДСТАВИТ,
ФЕДЕРАЛЬН,ГОСУДАРСТВЕНН,МЕЖДУНАРОДН,ОРГАНИЗАЦИ,ПРОИЗВОДСТВЕН,ПРОИЗВОД,РАЙОН,ПТИЦЕФАБРИК,ФАБРИК,ЗАКРЫТ,ОТКРЫТ,АКЦИОНЕРН,
МАШИНОСТРО,ГОРОДСК,СЕВЕРН,СЕВЕРО,ЮЖНО-,ЦЕНТР,ФИРМ,ГЛАВН,УПРАВ,ОБЩЕСТ,КОМПАНИ,МУНИЦИПАЛЬН,ДЕТСК,ТЕАТР,ТАНЦ,
ДЕЯТЕЛЬН,ОСУЩЕСТВ,ФЕДЕРАЦ,ПРОФСОЮЗ,ФИНУПР,СТАВРОПОЛЬСК,ЧАСОВЕНСК,БРОННИЦК,СТУПИНС,ОБЛАСТ,ДХООО,ШКОЛ,БОЛЬНИЦ,
ПОЛИКЛИНИК,ТОРГОВ,СТРОИТ]', CHR(10)), CHR(13)) AS s
FROM DUAL
),
stop_all AS (
SELECT /*+ MATERIALIZE */ W FROM (
SELECT ' ' || TRIM(REGEXP_SUBSTR(s, '[^,]+', 1, LEVEL)) || ' ' AS W
FROM stop_w CONNECT BY LEVEL <= REGEXP_COUNT(s, ',') + 1
UNION ALL
SELECT ' ' || TRIM(REGEXP_SUBSTR(s, '[^,]+', 1, LEVEL))
FROM stop_p CONNECT BY LEVEL <= REGEXP_COUNT(s, ',') + 1
)
),
src AS (
SELECT DISTINCT NAIMEN
FROM SH.UCH_VSE
WHERE NAIMEN IS NOT NULL
-- AND ROWNUM <= 20000 -- пробный прогон
),
norm AS ( -- верхний регистр, латиница->кириллица, чистка запятых и пробелов
SELECT NAIMEN,
TRIM(REGEXP_REPLACE(
TRANSLATE(UPPER(NAIMEN), 'ABCEHKMOPTXY', 'АВСЕНКМОРТХУ'),
'[,;[:space:]]+', ' ')) AS R
FROM src
),
pre AS ( -- вырезаем шум (ЧП/ИП/НОТАРИУС/Г. МОСКВЫ/...) из ЛЮБОГО места строки
SELECT NAIMEN, R,
TRIM(REGEXP_REPLACE(' ' || R || ' ',
'( (ЧАСТН[А-ЯЁ]*|ПРЕДПРИНИМАТЕЛ[А-ЯЁ]*|ПРЕДПР[А-ЯЁ]*\.?|ПР-ЛЬ|ПР-К|ИНДИВИД[А-ЯЁ]*\.?|ИП|ЧП|ПБОЮЛ|ФЛ'
|| '|НОТАРИУС[А-ЯЁ]*|АДВОКАТ|КПП|[0-9]+|Г\.? [А-ЯЁ-]{4,}|ГОР\.? [А-ЯЁ-]{4,}))+( |$)',
' ')) AS BODY
FROM norm
),
x AS (
SELECT NAIMEN, BODY,
CASE WHEN BODY <> R THEN 1 ELSE 0 END AS HAS_PREF,
-- A: Фамилия Имя Отчество (хвост любой)
REGEXP_SUBSTR(BODY,
'^([А-ЯЁ][-А-ЯЁ]{2,} [А-ЯЁ][-А-ЯЁ]+ ([-А-ЯЁ]{2,}(ИЧ|ЫЧ|ВНА|ИЧНА)|[-А-ЯЁ]+ (ОГЛЫ|ОГЛУ|КЫЗЫ|УГЛИ|УУЛУ)))( |$)',
1, 1, 'c', 1) AS FA,
-- B: Фамилия И.О. / Фамилия И О / И.О. Фамилия
NVL(
REGEXP_SUBSTR(BODY,
'^([А-ЯЁ][-А-ЯЁ]{2,} ([А-ЯЁ]\. ?[А-ЯЁ]\.?|[А-ЯЁ] [А-ЯЁ]\.?|[А-ЯЁ]\.))( |$)', 1, 1, 'c', 1),
REGEXP_SUBSTR(BODY,
'^([А-ЯЁ]\. ?([А-ЯЁ]\. ?)?[А-ЯЁ][-А-ЯЁ]{2,})( |$)', 1, 1, 'c', 1)) AS FB,
-- C: Фамилия Имя или одна фамилия (слабый признак)
CASE WHEN BODY <> R AND REGEXP_LIKE(BODY, '^[А-ЯЁ][-А-ЯЁ]{3,}$') THEN BODY
ELSE REGEXP_SUBSTR(BODY, '^([А-ЯЁ][-А-ЯЁ]{2,} [А-ЯЁ][-А-ЯЁ]{2,})( |$)', 1, 1, 'c', 1)
END AS FC
FROM pre
),
y AS (
SELECT NAIMEN, BODY,
CASE WHEN FA IS NOT NULL THEN 'A'
WHEN FB IS NOT NULL THEN 'B'
WHEN FC IS NOT NULL AND (HAS_PREF = 1 OR FC = BODY) THEN 'C' END AS TIER,
COALESCE(FA, FB, CASE WHEN HAS_PREF = 1 OR FC = BODY THEN FC END) AS FIO
FROM x
),
z AS (
SELECT y.*,
REGEXP_SUBSTR(FIO, '[А-ЯЁ][-А-ЯЁ]{2,}') AS SURN,
' ' || TRIM(REGEXP_REPLACE(CASE WHEN TIER = 'C' THEN BODY ELSE FIO END,
'[^А-ЯЁ0-9-]+', ' ')) || ' ' AS TOK
FROM y
),
res AS (
SELECT NAIMEN, FIO, TIER,
CASE WHEN TIER = 'C' AND NOT REGEXP_LIKE(SURN,
'(ОВ|ЕВ|ЁВ|ИН|ЫН|ИЙ|ЫЙ|ОЙ|ЯН|ЯНЦ|ЕЦ|ЕНОК|ИЧ|УК|ЮК|АК|ЯК|ИК|ЫХ|ИХ|ХАН|БЕК|БАЙ|[АЕИОУЮЯ])$')
THEN 0 ELSE 1 END AS END_OK,
CASE WHEN FIO IS NOT NULL
THEN (SELECT MIN(TRIM(st.W)) FROM stop_all st WHERE INSTR(z.TOK, st.W) > 0)
END AS STOP_WORD
FROM z
),
fin AS (
SELECT NAIMEN, FIO, TIER, STOP_WORD,
CASE WHEN FIO IS NULL THEN '2_НЕ_ФИО: форма'
WHEN END_OK = 0 THEN '3_НЕ_ФИО: окончание фамилии'
WHEN STOP_WORD IS NOT NULL THEN '4_НЕ_ФИО: стоп-слово'
ELSE '1_OK' END AS STATUS
FROM res
)
-- ВАРИАНТ 1: итоговый список ФИО
SELECT STATUS, STOP_WORD, NAIMEN FROM fin WHERE STATUS <> '1_OK' ORDER BY STATUS, NAIMEN;