Гость
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Склонение ФИО в postgres как сделать? / 12 сообщений из 12, страница 1 из 1
20.11.2011, 02:22
    #37535252
PG81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
Склонение ФИО в postgres как сделать? Есть ли готовые решения планые бесплатные не важно.Нужно очень срочно.
...
Рейтинг: 0 / 0
21.11.2011, 15:01
    #37536976
Author the new one
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
PG81,

Довольно давно делал склонение эвристически (по отчеству определяем пол, далее тупо перечисляем варианты - мужик, фамилии на "-ОВ/ИН/МАН/ШТЕЙН/твердый согласный" => "||У", "-ИЙ" => "ОМУ" и т.п.) на TSQL. Всех дел часа на два при наличии хорошего списка ФИО. Затыкалось реально на чем-то вроде Ли Сын Ман, Пу И или Уильям Генри Гейтс - ну там и так непонятно, как склонять.
...
Рейтинг: 0 / 0
21.11.2011, 15:26
    #37537031
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
в сети где-то валяются коды склонения ФИО (и даже профессий) не то в VB не то в т.н. "RSL" ( я не помню, перегонял ли из одного в другое. кажется перегонял. где-то у меня VBA-шное валяется. могу взглянуть, если не найдёте).

- простым гуглояндыксом ищем, затем в наш процедурный язык (plpgsql) - синтаксис массовой заменой перегоняем. (автор еще всё в одну строку засовывал, по индусски - защищался от чтения, видимо, бедняжко, я сильно не разгребал, так, слегка).

да, и это дело хорошо бы потом своими исключениями обвешать, но для этого надо врезаться вунутрь.
...
Рейтинг: 0 / 0
22.11.2011, 18:20
    #37539143
rostya
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
Задача сложнее, чем кажется.
Если не использовать большую базу фамилий и имен, а упирать на правила склонения, то они не так уж просты. см. Розенталь и др. "СПРАВОЧНИК ПО ПРАВОПИСАНИЮ, ПРОИЗНОШЕНИЮ, ЛИТЕРАТУРНОМУ РЕДАКТИРОВАНИЮ".

Есть исторически сложившиеся исключения.
Русские и нерусские имена и отчества склоняются они по-разному. А как без справочника фамилий определить русскость?
Есть фамилии, которые пишутся одинаково, но склоняются по-разному и т.п.
Базы со склонением фамилий достаточного объема в сети найти не удалось.

Когда надо было склонять в клиентской программе, делал так, чтобы пользователь мог исправить предлагаемый вариант.

Посмотрите http://morpher.ru/Competition
Там есть ссылки в т.ч. на исходники.
...
Рейтинг: 0 / 0
22.11.2011, 18:54
    #37539192
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
rostyaЗадача сложнее, чем кажется.судя по всему
- http://www.sql.ru/forum/actualthread.aspx?tid=280539&pg=1&mid=11630728#11630728
топик-стартер подключил dll под это дело (в сети таки валялась, когда я искал код)

откуда мораль - виндузятник :)
...
Рейтинг: 0 / 0
22.11.2011, 18:57
    #37539197
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
rostya,

ЗЫ по вашей ссылке
>> Автор – Железняков Юрий Юрьевич aka SuperJur.
- а вот его RSL-поделие я и перетачивал.
...
Рейтинг: 0 / 0
22.11.2011, 23:41
    #37539506
PG81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
да подключил padeg.dll,
отсюда нашел
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=412
Щас пытаюсь найти создателей, купить ее у них. Что-то не выходят на связь
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
17.02.2018, 18:58
    #39603531
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
PG81,

вот ора--калоеды настрогали:

Склонение фамилий. (Вариант решения)

я парочку оттуда сёня передрал вчерне. ещё варианта 3--4 осталось:

вот этот:
13791019
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
--create extension if not exists fuzzystrmatch;

--fio_case
create or replace function term( in s text,in t text ) returns boolean
AS
$$
begin
	raise notice 's	%,	t	%',s,t;
	if COALESCE(length(s),0)<COALESCE(length(t),0) then return false;
	--elsif substr(lower(s),-length(t))=lower(t) then return true;
	elsif right(lower(s),length(t))=lower(t) then return true;
	end if;
	return false;
end;
$$
IMMUTABLE 
LANGUAGE plpgsql;

--
create or replace function chng(
	s in out text
	,p in int
	,n in integer
	,pr in text
	,pd in text
	,pv in text
	,pt in text
	,pp in text
	)
RETURNS TEXT
LANGUAGE plpgsql
AS
$$
 begin
	raise notice 's	%,	p	%,n	%,pr	%,pd	%,pv	%,pt	%,pp	%;',s,p,n,pr,pd,pv,pt,pp;
	if length(s)>1 then
		--RAISE NOTICE 'length(s)	%,n	%)',length(s),n;
		s:=substr(s,1,length(s)-n)||
		case when --substr(s,-1)=upper(substr(s,-1)) then
					right(s,1)=upper(right(s,1)) then
			upper(case p
					when 2 then pr when 3 then pd when 4 then pv
					when 5 then pt when 6 then pp end)
		else
			lower(case p when 2 then pr when 3 then pd when 4 then pv
						when 5 then pt when 6 then pp end)
		end;
		
	end if;
	RAISE NOTICE 'length(s)	%,n	% ,S	%)',length(s),n, S;
	return;
end;
$$
immutable ;




create or replace function fio_case(
		IN p_fio text			-- ФИО
		,IN p_padzh text		-- падеж: 'р'|'Р'|'2'-родительный,'д'|'Д'|'3'-дательный,
												-- 'в'|'В'|'4'-винительный,'т'|'Т'|'5'-творительный,
												-- 'п'|'П'|'6'-предложный
		,IN p_fio_fmt text DEFAULT 'ФИО' -- формат ФИО: 'Алексей Немов'->'ИФ',
																 -- 'Ольга Львовна Гидова-Бережная'->'ИОФ'
		,IN p_sex text DEFAULT null -- пол: 'ж'|'Ж'|'м'|'М'
	) returns text
AS $$
	--TODO разобрать сразу на части сопоставить кол-ва в формате и в строке
	--определить (если частей разно) состав(частей) и падеж входящей конструкции по окончаниям
	-- дерево + веса "Пульхерия Иван Вартанович" "Пульхерия Иванна Вартановна" "Пульхерия Ивановна Вартанович"
	-- добавить параметр --"вх-падеж"(вх) и 2 флага приоритетов , если деф-параметры секас и вх-падёж противоречат приоритетам разбора
	-- мей-би не булевы, а весовые
	-- и оттуда к нормализации и выводам
	-- + таблица маргиналий оглы улы кезы кезим керим ?беге  и пр.
	-- фамильные батыр хан и т.п. + снис/чене
	-- отпиливание по частям 
		
		-- падежная форма ФИО for Oracle 10g+;
		-- hexcept,hexcept@gmail.com;
DECLARE
	l_pdzh_chr varchar(4);
	l_pdzh int;
	l_sex varchar(4):=substr(trim(lower(p_sex)),1,1);
	l_tailchr varchar(4);
	l_nmlen integer;	--(4,0);
	a_names	text[];
	l_name_s text:=null;
	l_name_n text:=null;
	l_fio text:=null;
	l_fname text:=null;
	l_mname text:=null;
	l_fullname text:=regexp_replace(ltrim(rtrim(p_fio,' -'),' -'),'\s*([ \-]\s*)','\1','ig');
	l_pos int;
	l_fio_fmt varchar(10):=COALESCE(upper(substr(ltrim(p_fio_fmt),1,3)),'ФИО');
	l_ch varchar(1):=chr(7); -- замена символа '.'
--
--
begin -- fio_case()
	--if soundex(p_fio) is not null then return l_fullname;	end if; -- latin
	
	l_pdzh_chr:=upper(substr(p_padzh,1,1)); -- падеж
	
	l_pdzh:=case l_pdzh_chr
			when 'И' then 1 when 'Р' then 2 when 'Д' then 3
			when 'В' then 4 when 'Т' then 5 when 'П' then 6 else 0 end;
			
	if l_pdzh=0 and l_pdzh_chr ~'[0-9]' then
		l_pdzh:=l_pdzh_chr::int;	-- COALESCE(to_number(l_pdzh_chr),0);
	end if;

	if l_pdzh not between 2 and 6 then return p_fio; end if;
	raise notice 'l_ch %, %,	%, 	%,%',l_ch,chr(7),l_pdzh_chr,l_pdzh,l_fio_fmt;
	-- формат ФИО:
	if l_fio_fmt is null or length(l_fio_fmt)>3
		--or ltrim(l_fio_fmt,'ФИО') is not null
		or l_fio_fmt ~'Ф.*Ф'	--strpos(l_fio_fmt,'Ф',1,2)>0
		or l_fio_fmt ~'И.*И'	--strpos(l_fio_fmt,'И',1,2)>0
		or l_fio_fmt ~'О.*О'	--or strpos(l_fio_fmt,'О',1,2)>0
	then return p_fio;
	end if;
	raise notice 'l_ch %, %,	%, 	%',l_ch,chr(7),l_pdzh_chr,l_pdzh;
	-- ФИО:
	/*
	l_fullname:=trim(
		replace(
			replace(case when strpos(l_fullname,'	')>0
				then regexp_replace(l_fullname,' +',' ') else l_fullname
				end,' -','-')
			,'- ','-')
			);
	*/
	--		\1
	if l_fullname is null then return p_fio;
	elsif strpos(l_fullname,'.')>0 then -- случай 'Иван И.Якин'
		l_fullname:=regexp_replace(l_fullname,'(\w)\.(\w)','\1'||l_ch||' \2');
	end if;
-- оглы,кызы:
	if strpos(lower(l_fullname),'оглы')>0 then
		l_fullname:=regexp_replace(l_fullname,' ([оО][гГ][лЛ][ыЫ])','_\1');
		l_sex:=COALESCE(l_sex,'м');
	elsif strpos(lower(l_fullname),'кызы')>0 then
		l_fullname:=regexp_replace(l_fullname,' ([кК][ыЫ][зЗ][ыЫ])','_\1');
		l_sex:=COALESCE(l_sex,'ж');
	end if;
	--unnest(string_to_array(l_fio_fmt,null)) with ordinality
	a_names := string_to_array(l_fullname,' ');
	if strpos(l_fio_fmt,'Ф')>0 then
		--l_name_s:=regexp_substr(l_fullname,'[^ ]+',1,strpos(l_fio_fmt,'Ф'));
		l_name_s:= a_names[strpos(l_fio_fmt,'Ф')];
	end if;
	if strpos(l_fio_fmt,'И')>0 then
		--l_fname:=regexp_substr(l_fullname,'[^ ]+',1,strpos(l_fio_fmt,'И'));
		l_fname := a_names[strpos(l_fio_fmt,'И')];
	end if;
	if strpos(l_fio_fmt,'О')>0 then
		--l_mname:=regexp_substr(l_fullname,'[^ ]+',1,strpos(l_fio_fmt,'О'));
		l_mname := a_names[strpos(l_fio_fmt,'О')];
	end if;

	l_nmlen:=COALESCE(length(l_name_s),0);
	if COALESCE(l_sex,'z') not in ('м','ж') then -- пол не определен,
	-- пробуем определить его по отчеству:
		if upper(l_mname) like '%ИЧ' then l_sex:='м';
		elsif upper(l_mname) like '%НА' then l_sex:='ж';
		-- по фамилии:
		elsif strpos(',ва,на,ая,',','||substr(lower(l_name_s),-2)||',')>0 then
			l_sex:='ж';
		elsif strpos(',ов,ев,ёв,ин,ев,ий,ый,',','||substr(lower(l_name_s),-2)||',')>0
		then l_sex:='м';
		else l_sex:='ж';
		end if;
	end if;
	if l_name_s is not null then	-- фамилия
		-- сдвоенная фамилия:
		if strpos(l_name_s,'-')>0 and lower(l_name_s) not like 'тер-%' then
			l_name_n:=
				substr(l_name_s,1,strpos(l_name_s,'-')-1)||' '||l_fname||' '||l_mname;
			l_fio:=fio_case(l_name_n,p_padzh,'ФИО',l_sex);
			l_name_n:=substr(l_fio,1,strpos(l_fio,' ')-1)||'-';
			l_name_s:=substr(l_name_s,strpos(l_name_s,'-')+1);
		end if;

		raise notice 'tail	%'	,lower(right(l_name_s,1));
		l_tailchr:=	lower(right(l_name_s,1));	--lower(substr(l_name_s,-1));
		
		if l_sex='м' then	-- мужчины
			if COALESCE(strpos('оеуюиэы',l_tailchr),0)=0 then
				if l_tailchr='в' then
					l_name_s:=chng(l_name_s,l_pdzh,0,'а','у','а','ым','е');
				elsif l_tailchr='н' and term(l_name_s,'ин') then
					l_name_s:=chng(l_name_s,l_pdzh,0,'а','у','а','ым','е');
				elsif l_tailchr='ц' and term(l_name_s,'ец') then
					if l_nmlen>3 and strpos('аец,еец,иец,оец,уец',substr(l_name_s,-3))>0 then
						l_name_s:=chng(l_name_s,l_pdzh,2,'йца','йцу','йца','йцем','йце');
					elsif
						l_nmlen>3
						and strpos('тец,бец,вец,мец,нец,рец,сец'	--,lower(substr(l_name_s,-3))
																,strpos
							)>0
						and strpos('а,е,и,о,у,ы,э,ю,я,ё'	--,lower(substr(l_name_s,-4,1))
														,lower(left(right(l_name_s,4),1))
						)>0
					then l_name_s:=chng(l_name_s,l_pdzh,2,'ца','цу','ца','цом','це');
					elsif l_nmlen>3 and --lower(substr(l_name_s,-3)
									lower(right(l_name_s,3)
						)='лец' then
						l_name_s:=chng(l_name_s,l_pdzh,2,'ьца','ьцу','ьца','ьцом','ьце');
					else l_name_s:=chng(l_name_s,l_pdzh,0,'а','у','а','ом','е');
					end if;
				elsif l_tailchr='х'
					and (term(l_name_s,'их') or term(l_name_s,'ых'))
				then l_name_s:=chng(l_name_s,l_pdzh,0,null,null,null,null,null);
				elsif strpos('б,г,д,ж,з,л,м,н,п,р,с,т,ф,х,ц,ч,ш,щ',l_tailchr)>0
				then l_name_s:=chng(l_name_s,l_pdzh,0,'а','у','а','ом','е');
				elsif l_tailchr='я'
					and not(term(l_name_s,'ия') or term(l_name_s,'ая'))
				then
					l_name_s:=chng(l_name_s,l_pdzh,1,'и','е','ю','ей','е');
				elsif l_tailchr='а'
					and not(term(l_name_s,'иа') or term(l_name_s,'уа'))
				then
					l_name_s:=chng(l_name_s,l_pdzh,1,'и','е','у','ой','е');
				elsif l_tailchr='ь' then
					l_name_s:=chng(l_name_s,l_pdzh,1,'я','ю','я','ем','е');
				elsif l_tailchr='к' then
					if l_nmlen>4 and term(l_name_s,'ок') then
						l_name_s:=chng(l_name_s,l_pdzh,2,'ка','ку','ка','ком','ке');
					elsif l_nmlen>4
						and (term(l_name_s,'лек') or term(l_name_s,'рек'))
					then l_name_s:=chng(l_name_s,l_pdzh,2,'ька','ьку','ька','ьком','ьке');
					else
						l_name_s:=chng(l_name_s,l_pdzh,0,'а','у','а','ом','е');
					end if;
				elsif l_tailchr='й' then
					if l_nmlen>4 then
						if (term(l_name_s,'ский') or term(l_name_s,'цкий')) then
							l_name_s:=chng(l_name_s,l_pdzh,2,'ого','ому','ого','им','ом');
						elsif term(l_name_s,'ой') then
							l_name_s:=chng(l_name_s,l_pdzh,2,'ого','ому','ого','им','ом');
						elsif term(l_name_s,'ый') then
							l_name_s:=chng(l_name_s,l_pdzh,2,'ого','ому','ого','ым','ом');
						elsif
							strpos('рий,жий,лий,вий,дий,бий,гий,зий,мий,ний,пий,сий,фий,хий',
								--lower(substr(l_name_s,-3))
								lower(right(l_name_s,3))
								)>0
						then l_name_s:=chng(l_name_s,l_pdzh,1,'я','ю','я','ем','и');
						elsif term(l_name_s,'ий') then
							l_name_s:=chng(l_name_s,l_pdzh,2,'его','ему','его','им','им');
						else l_name_s:=chng(l_name_s,l_pdzh,1,'я','ю','я','ем','е');
						end if;
					else l_name_s:=chng(l_name_s,l_pdzh,1,'я','ю','я','ем','е');
					end if;
				end if;
			end if;
			
			elsif l_sex='ж' then	-- женщины
				if strpos('ова,ева,ына,ина,ена'	--,lower(substr(l_name_s,-3))
												,lower(right(l_name_s,3))
					)>0 then
					l_name_s:=chng(l_name_s,l_pdzh,1,'ой','ой','у','ой','ой');
				elsif term(l_name_s,'ая') and --lower(substr(l_name_s,-3,1))='ц'
												lower(left(right(l_name_s,3),1))='ц'
				then
					l_name_s:=chng(l_name_s,l_pdzh,2,'ей','ей','ую','ей','ей');
				elsif term(l_name_s,'ая') then
					l_name_s:=chng(l_name_s,l_pdzh,2,'ой','ой','ую','ой','ой');
				elsif term(l_name_s,'ля') or term(l_name_s,'ня') then
					l_name_s:=chng(l_name_s,l_pdzh,1,'и','е','ю','ей','е');
				elsif term(l_name_s,'а') and --lower(substr(l_name_s,-2,1)) in ('д')
											lower(left(right(l_name_s,2),1)) in ('д')
				then
					l_name_s:=chng(l_name_s,l_pdzh,1,'ы','е','у','ой','е');
				end if;
			end if;
		end if;

		if l_fname is not null then	-- имя
		l_tailchr:=	--lower(substr(l_fname,-1));
					lower(right(l_fname,1));
		if l_sex='м' then	-- мужчины
			--if COALESCE(strpos('е,и,у',l_tailchr),0)=0 then
			if not l_tailchr ~ '[еиу]' then
				if upper(l_fname)='ЛЕВ' then
					l_fname:=chng(l_fname,l_pdzh,2,'ьва','ьву','ьва','ьвом','ьве');
				elsif strpos('б,в,г,д,з,ж,к,м,н,п,р,с,т,ф,х,ц,ч,ш,щ',l_tailchr)>0 then
					l_fname:=chng(l_fname,l_pdzh,0,'а','у','а','ом','е');
				elsif l_tailchr='а' then	l_fname:=chng(l_fname,l_pdzh,1,'ы','е','у','ой','е');
				elsif l_tailchr='о' then	l_fname:=chng(l_fname,l_pdzh,1,'а','у','а','ом','е');
				elsif l_tailchr='я' then
					if term(l_fname,'ья') then	l_fname:=chng(l_fname,l_pdzh,1,'и','е','ю','ей','е');
					elsif term(l_fname,'ия') then
							l_fname:=chng(l_fname,l_pdzh,1,'и','е','ю','ей','е');
					else	l_fname:=chng(l_fname,l_pdzh,1,'и','е','ю','ей','е');
					end if;
				elsif l_tailchr='й' then
					if term(l_fname,'ай') then	l_fname:=chng(l_fname,l_pdzh,1,'я','ю','я','ем','е');
					else
						if term(l_fname,'ей') then
							l_fname:=chng(l_fname,l_pdzh,1,'я','ю','я','ем','е');
						else	l_fname:=chng(l_fname,l_pdzh,1,'я','ю','я','ем','и');
						end if;
					end if;
				elsif l_tailchr='ь' then	l_fname:=chng(l_fname,l_pdzh,1,'я','ю','я','ем','е');
				elsif l_tailchr='л' then
					if term(l_fname,'авел') then
						l_fname:=chng(l_fname,l_pdzh,2,'ла','лу','ла','лом','ле');
					else	l_fname:=chng(l_fname,l_pdzh,0,'а','у','а','ом','е');
					end if;
				end if;
			end if;
		elsif l_sex='ж' then	-- женщины
			if l_tailchr='а' and COALESCE(length(l_fname),0)>1 then
				if strpos('га,ха,ка,ша,ча,ща,жа'	--,lower(substr(l_fname,-2)))>0
						,lower(right(l_fname,2)))>0
				then
					l_fname:=chng(l_fname,l_pdzh,1,'и','е','у','ой','е');
				else	l_fname:=chng(l_fname,l_pdzh,1,'ы','е','у','ой','е');
				end if;
			elsif l_tailchr='я' and COALESCE(length(l_fname),0)>1 then
				if term(l_fname,'ия') then
				 if strpos(
					'Адл,Ал,Алф,Альф,Ас,Асл,Аф,Баг,Вал,Васв,Васф,Вел,'||
					'Гал,Гаф,Гольф,Гул,Гульс,Гульф,Дал,Дан,Дар,Дел,Дил,Дилф,Дульф,Жар,'||
					'Зак,Зал,Зан,Зар,Зельф,Зил,Зулф,Зульф,Ид,Ильс,Кадр,Кал,Каф,Кем,'||
					'Лам,Лутф,Мад,Марз,Мунз,Над,Наж,Наз,Нак,Нал,Нурз,Нур,Нурс,Нюр,'||
					'Рав,Раз,Рал,Рамз,Рам,Ран,Расм,Раф,Роз,Руз,Рум,Руф,'||
					'Сав,Сад,Сал,Сан,Сар,Саф,Сол,Сур,Суф,Тал,Тасл,Тат,Ульв,'||
					'Фавз,Фак,Фал,Фанз,Фан,Фатх,Фик,Фирз,Хам,Хан,Шамг,Шамс,Элф,',
					replace(initcap(l_fname)||',','ия,',','))>0 -- Альфия,Нурия..
				 then	l_fname:=chng(l_fname,l_pdzh,1,'и','е','ю','ей','е');
				 else	l_fname:=chng(l_fname,l_pdzh,1,'и','и','ю','ей','и'); -- Мария,Юлия..
				 end if;
				else	l_fname:=chng(l_fname,l_pdzh,1,'и','е','ю','ей','е');
				end if;
			 elsif l_tailchr='ь' then
				if term(l_fname,'вь') then	l_fname:=chng(l_fname,l_pdzh,1,'и','и','ь','ью','и');
				elsif term(l_fname,'ль') and strpos(
				 'Айгу,Айгю,Айсе,Асе,Бактыгу,Гуза,Гузе,Гузя,Гюзе,Гюзя,'||
				 'Джанаргу,Жангу,Идигу,Мавджигу,Миннегузе,Миннегу,Миргу,'||
				 'Назгу,Нургу,Нико,Оразгу,Орозгу,Сапарку,Фирангю,Шахрагу,',
				 replace(initcap(l_fname)||',','ль,',','))>0 -- несклоняемые Айгуль,Гузель..
				then null;
				else	l_fname:=chng(l_fname,l_pdzh,1,'и','и','ь','ью','ье');
				end if;
			 end if;
		end if;
	 end if;
	 if l_mname is not null then	-- отчество
		l_tailchr:=	--lower(substr(l_mname,-1));
					lower(right(l_mname,1));
		if l_sex='м' then	-- мужчины
			if l_tailchr='ч' then	l_mname:=chng(l_mname,l_pdzh,0,'а','у','а','ем','е'); end if;
		elsif l_sex='ж' then	-- женщины
			if l_tailchr='а' and length(l_mname)<>1 then
				l_mname:=chng(l_mname,l_pdzh,1,'ы','е','у','ой','е');
			end if;
		end if;
	end if;
	-- окончательная конкатенация:
	l_fio_fmt:=COALESCE(upper(substr(ltrim(p_fio_fmt),1,3)),'ФИО');
	l_fullname:='';
	l_pos:=1;
	loop
		if l_pos>1 then l_fullname:=l_fullname||' '; end if;
		l_fullname:=l_fullname||
			case substr(l_fio_fmt,l_pos,1)
			when 'Ф' then concat(l_name_n,l_name_s) when 'И' then l_fname when 'О' then l_mname
			end;
		l_pos:=l_pos+1;
		if l_pos>COALESCE(length(l_fio_fmt),0) then exit; end if;
	end loop;
raise notice 'l_fullname	%',l_fullname;
return
	replace(replace(replace(replace(replace(replace(replace(COALESCE(ltrim(rtrim(
	l_fullname,' -'),' -'),ltrim(rtrim(case
		when strpos(p_fio,'	')>0 then regexp_replace(p_fio,' +',' ')
		else p_fio end,' -'),' -')),'	',' '),l_ch||' ','.'),l_ch,'.'),
		'_о',' о'),'_О',' О'),'_к',' к'),'_К',' К');
end;-- fio_case;
$$
immutable
LANGUAGE plpgsql;;
--------------




SELECT fio_case('Путин Владимир Владимирович', p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Гондурас-Чеши Арбуз Хозеевич', p,'ФИО'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Гондурас-Болеславская Арбуз Хоевна', p,'ФИО'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Хуан Хуанович Рохас-Кастильо', p,'ИОФ','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Хуан Хуанович Рохас-Кастильо', p,'ИОФ','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Гомон Ярослав Кузьмич', p,'ФИО' ,'м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Кузьмич Фаина Ярославна',p,'ФИО' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Кузьмич Фаина Ярославна',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Кузьмич Фаина Ярослав беге',p,'ФИО' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
union all
SELECT fio_case('Путин Владимир Владимирович', p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Перес -Палех Андреас Хозеевич', p,'ФИО','м'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)

UNION all SELECT 
	fio_case('Гондурас-Чеши Арбуз Хозеевич', p,'ФИО','м'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Гондурас-Болеславская Медея - Анна -Аргуз Хоревна', p,'ФИО','ж'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Хуан Хуанович Рохас-Кастильо', p,'ИОФ','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Хуана Хуановна Хуанович-Рохас-Кастильо', p,'ИОФ','ж' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Гомон Ярослав Кузьмич', p,'ФИО' ,'м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Кузьмич Фаина Ярославна',p,'ФИО','ж' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Кузьмич-Ильич-Кащей Лич-Серый-Сыч Янусович',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Кузьмич Фаина Ярослав-беге',p,'ФИО','ж'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	fio_case('Карабас-Барабас-Бармалей Оглы-Бей Момыш-Улы',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
--Алия,Сания,Асия 
UNION all SELECT 
	fio_case('Карабас-Барабас-Бармалей Алия-Сания- Рея-Лорелея-Галерея-Галера-Холера -Глория -Юлия- Гюльчатай Момыш-кызы-Петровна',p,'ФИО','ж' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
--какучия гиви
UNION all SELECT 
	fio_case('Берия-Какучия-Могучая-Кипиани-Самошвали-Руставели-Шенгелия-Джугашвили Алия-Сания- Гиви Резоевич',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
;



и ещо один намёток.

надо подумать, как и можно ли фтс--словари заюзать
...
Рейтинг: 0 / 0
17.02.2018, 19:22
    #39603533
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
и вот такой набросок 2563001 срисовал

добавил зачаток врапера для фио, и вся табла дерева ветвлений в коде.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
--http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=282734&msg=2563001

DROP FUNCTION ora_padej(text,char,int,text);
CREATE OR REPLACE FUNCTION ora_padej(
	IN p_Word		text
	,IN p_WType	char
	,IN p_POL		int
	,IN p_PadOut	text
	)
RETURNS text 
LANGUAGE plpgsql
AS 
$$
-- TODO ?отделить постфикс--определитель от именительного вариативного.
-- Ро(залия)А(залия)|(АлиЯ) дат и пр азалии вс АлиЕ
-- и/или включить ударность в таблицу 
-- и предкурсор слов с альтернативной ударностью
-- окончаний
-- 
DECLARE
	-- Курсор для выборки правил склонения
	cs1 SCROLL CURSOR FOR SELECT t.z, t.rp, t.dp, t.tip, t.pol, t.vp, t.tp, t.pp
		FROM (
SELECT * FROM (values 
(text'А',text'Ы',text'Е',char'F',smallint'1',text'У',text'ОЙ',text'Е')
,('АД','АДА','АДУ','F','1','АДА','АДОМ','АДЕ')
,('АЙ','АЯ','АЮ','F','1','АЯ','АЕМ','АЕ')
,('АК','АКА','АКУ','F','1','АКА','АКОМ','АКЕ')
,('АН','АНА','АНУ','F','1','АНА','АНОМ','АНЕ')
,('АС','АСА','АСУ','F','1','АСА','АСОМ','АСЕ')
,('АЧ','АЧА','АЧУ','F','1','АЧА','АЧЕМ','АЧЕ')
,('ЕВ','ЕВА','ЕВУ','F','1','ЕВА','ЕВЫМ','ЕВЕ')
,('ЕД','ЕДА','ЕДУ','F','1','ЕДА','ЕДОМ','ЕДЕ')
,('ЕЙ','ЕЯ','ЕЮ','F','1','ЕЯ','ЕЕМ','ЕЕ')
,('ЕКР','ЕКРА','ЕКРУ','F','1','ЕКРА','ЕКРОМ','ЕКРЕ')
,('ЕР','ЕРА','ЕРУ','F','1','ЕРА','ЕРОМ','ЕРЕ')
,('ЕСТЬ','ЕСТЯ','ЕСТЮ','F','1','ЕСТЯ','ЕСТЕМ','ЕСТЕ')
,('ЕС','ЕСА','ЕСУ','F','1','ЕСА','ЕСОМ','ЕСЕ')
,('ЕЦ','ЦА','ЦУ','F','1','ЦА','ЦОМ','ЦЕ')
,('ЕХ','ЕХА','ЕХУ','F','1','ЕХА','ЕХОМ','ЕХЕ')
,('ЖА','ЖУ','ЖЕ','F','1','ЖУ','ЖЕЙ','ЖЕ')
,('ЗЕ','ЗЕ','ЗЕ','F','1','ЗЕ','ЗЕ','ЗЕ')
,('ИЙ','ОГО','ОМУ','F','1','ОГО','ИМ','ОМ')
,('ИК','ИКА','ИКУ','F','1','ИКА','ИКОМ','ИКЕ')
,('ИМ','ИМА','ИМУ','F','1','ИМА','ИМОМ','ИМЕ')
,('ИН','ИНА','ИНУ','F','1','ИНА','ИНЫМ','ИНЕ')
,('ИХ','ИХ','ИХ','F','1','ИХ','ИХ','ИХ')
,('ИЧ','ИЧА','ИЧУ','F','1','ИЧА','ИЧОМ','ИЧЕ')
,('ЙМ','ЙМА','ЙМУ','F','1','ЙМА','ЙМОМ','ЙМЕ')
,('КА','КУ','КЕ','F','1','КУ','КОЙ','КЕ')
,('КО','КО','КО','F','1','КО','КО','КО')
,('ЛА','ЛУ','ЛЕ','F','1','ЛУ','ЛОЙ','ЛЕ')
,('ЛИ','ЛИ','ЛИ','F','1','ЛИ','ЛИ','ЛИ')
,('ЛН','ЛНА','ЛНУ','F','1','ЛНА','ЛНОМ','ЛНЕ')
,('ЛО','ЛО','ЛО','F','1','ЛО','ЛО','ЛО')
,('ЛЬ','ЛЯ','ЛЮ','F','1','ЛЯ','ЛЕМ','ЛЕ')
,('Н','НА','НУ','F','1','НА','НОМ','НЕ')
,('НД','НДА','НДУ','F','1','НДА','НДОМ','НДЕ')
,('НО','НО','НО','F','1','НО','НО','НО')
,('НТ','НТА','НТУ','F','1','НТА','НТОМ','НТЕ')
,('НЬ','НЯ','НЮ','F','1','НЯ','НЕМ','НЕ')
,('ОВ','ОВА','ОВУ','F','1','ОВА','ОВЫМ','ОВЕ')
,('ОЙ','ОГО','ОМУ','F','1','ОГО','ЫМ','ОМ')
,('ОК','КА','КУ','F','1','КА','КОМ','КЕ')
,('РЬ','РЯ','РЮ','F','1','РЯ','РЕМ','РЕ')
,('УЖ','УЖА','УЖУ','F','1','УЖА','УЖЕМ','УЖЕ')
,('УК','УКА','УКУ','F','1','УКА','УКОМ','УКЕ')
,('УН','УНА','УНУ','F','1','УНА','УНОМ','УНЕ')
,('УС','УСА','УСУ','F','1','УСА','УСОМ','УСЕ')
,('УСЬ','УСЯ','УСЮ','F','1','УСЯ','УСЕМ','УСЕ')
,('УХ','УХА','УХУ','F','1','УХА','УХОМ','УХЕ')
,('ХА','ХУ','ХЕ','F','1','ХУ','ХОЙ','ХЕ')
,('ХО','ХО','ХО','F','1','ХО','ХО','ХО')
,('ЦА','ЦУ','ЦЕ','F','1','ЦУ','ЦЕЙ','ЦЕ')
,('ЦОЙ','ЦОЙ','ЦОЙ','F','1','ЦОЙ','ЦОЙ','ЦОЙ')
,('ША','ШУ','ШЕ','F','1','ШУ','ШЕЙ','ШЕ')
,('ШИ','ШИ','ШИ','F','1','ШИ','ШИ','ШИ')
,('ЫЙ','ОГО','ОМУ','F','1','ОГО','ЫМ','ОМ')
,('ЫК','ЫКА','ЫКУ','F','1','ЫКА','ЫКОМ','ЫКЕ')
,('ЫН','ЫНА','ЫНУ','F','1','ЫНА','ЫНОМ','ЫНЕ')
,('ЫХ','ЫХ','ЫХ','F','1','ЫХ','ЫХ','ЫХ')
,('ЫШ','ЫША','ЫШУ','F','1','ЫША','ЫШЕМ','ЫШЕ')
,('ЬМ','ЬМА','ЬМУ','F','1','ЬМА','ЬМОМ','ЬМЕ')
,('ЬЦ','ЬЦА','ЬЦУ','F','1','ЬЦА','ЬЦЕМ','ЬЦЕ')
,('ЮК','ЮКА','ЮКУ','F','1','ЮКА','ЮКОМ','ЮКЕ')
,('ЯТЬ','ЯТЯ','ЯТЮ','F','1','ЯТЯ','ЯТЕМ','ЯТЕ')
,('АК','АК','АК','F','2','АК','АК','АК')
,('АТЬ','АТЕРИ','АТЕРИ','F','2','АТЬ','АТЕРЬЮ','АТЕРИ')
,('АЯ','ОЙ','ОЙ','F','2','УЮ','ОЙ','ОЙ')
,('ВА','ВОЙ','ВОЙ','F','2','ВУ','ВОЙ','ВОЙ')
,('КА','КИ','КЕ','F','2','КУ','КОЙ','КЕ')
,('КО','КО','КО','F','2','КО','КО','КО')
,('НА','НОЙ','НОЙ','F','2','НУ','НОЙ','НЕ')
,('НД','НД','НД','F','2','НД','НД','НД')
,('ОЧЬ','ОЧЕРИ','ОЧЕРИ','F','2','ОЧЬ','ОЧЕРЬЮ','ОЧЕРИ')
,('РА','РЫ','РЕ','F','2','РУ','РОЙ','РЕ')
,('ТЕЙ','ТЕЙ','ТЕЙ','F','2','ТЕЙ','ТЕЙ','ТЕЙ')
,('ХА','ХИ','ХЕ','F','2','ХУ','ХОЙ','ХУ')
,('ЦА','ЦЫ','ЦЕ','F','2','ЦУ','ЦЕЙ','ЦЕ')
,('Ч','Ч','Ч','F','2','Ч','Ч','Ч')
,('ЩА','ЩИ','ЩЕ','F','2','ЩУ','ЩЕЙ','ЩЕ')
,('А','Ы','Е','N','1','У','ОЙ','Е')
,('АВ','АВА','АВУ','N','1','АВА','АВОМ','АВЕ')
,('АЙ','АЯ','АЮ','N','1','АЯ','АЕМ','АЕ')
,('АН','АНА','АНУ','N','1','АНА','АНОМ','АНЕ')
,('АР','АРА','АРУ','N','1','АРА','АРОМ','АРЕ')
,('АС','АСА','АСУ','N','1','АСА','АСОМ','АСЕ')
,('АТ','АТА','АТУ','N','1','АТА','АТОМ','АТЕ')
,('АХ','АХА','АХУ','N','1','АХА','АХОМ','АХЕ')
,('ДР','ДРА','ДРУ','N','1','ДРА','ДРОМ','ДРЕ')
,('ЕВ','ЬВА','ЬВУ','N','1','ЬВА','ЬВОМ','ЬВЕ')
,('ЕГ','ЕГА','ЕГУ','N','1','ЕГА','ЕГОМ','ЕГЕ')
,('ЕД','ЕДА','ЕДУ','N','1','ЕДА','ЕДОМ','ЕДЕ')
,('ЕЙ','ЕЯ','ЕЮ','N','1','ЕЯ','ЕЕМ','ЕЕ')
,('ЕК','ЕКА','ЕКУ','N','1','ЕКА','ЕКОМ','ЕКЕ')
,('ЕЛ','ЛА','ЛУ','N','1','ЛА','ЛОМ','ЛЕ')
,('ЕМ','ЕМА','ЕМУ','N','1','ЕМА','ЕМОМ','ЕМЕ')
,('ЕН','ЕНА','ЕНУ','N','1','ЕНА','ЕНОМ','ЕНЕ')
,('ЕР','ЕРА','ЕРУ','N','1','ЕРА','ЕРОМ','ЕРЕ')
,('ЕФ','ЕФА','ЕФУ','N','1','ЕФА','ЕФОМ','ЕФЕ')
,('ИД','ИДА','ИДУ','N','1','ИДА','ИДОМ','ИДЕ')
,('ИЙ','ИЯ','ИЮ','N','1','ИЯ','ИЕМ','ИЕ')
,('ИЛ','ИЛА','ИЛУ','N','1','ИЛА','ИЛОМ','ИЛЕ')
,('ИМ','ИМА','ИМУ','N','1','ИМА','ИМОМ','ИМЕ')
,('ИН','ИНА','ИНУ','N','1','ИНА','ИНЫМ','ИНЕ')
,('ИР','ИРА','ИРУ','N','1','ИРА','ИРОМ','ИРЕ')
,('ИС','ИСА','ИСУ','N','1','ИСА','ИСОМ','ИСЕ')
,('ИТ','ИТА','ИТУ','N','1','ИТА','ИТОМ','ИТЕ')
,('ИХ','ИХА','ИХУ','N','1','ИХА','ИХОМ','ИХЕ')
,('ИЧ','ИЧА','ИЧУ','N','1','ИЧА','ИЧЕМ','ИЧЕ') -- Ильич
,('ЛЛ','ЛЛА','ЛЛУ','N','1','ЛЛА','ЛЛОМ','ЛЛЕ')
,('ЛЬ','ЛЯ','ЛЮ','N','1','ЛЯ','ЛЕМ','ЛЕ')
,('МА','МУ','МЕ','N','1','МУ','МОЙ','МЕ')
,('ОВ','ОВА','ОВУ','N','1','ОВА','ОВЫМ','ОВЕ')
,('ОД','ОДА','ОДУ','N','1','ОДА','ОДОМ','ОДЕ')
,('ОН','ОНА','ОНУ','N','1','ОНА','ОМ','НЕ')
,('ОР','ОРА','ОРУ','N','1','ОРА','ОРОМ','ОРЕ')
,('РД','РДА','РДУ','N','1','РДА','РДОМ','РДЕ')
,('РС','РСА','РСУ','N','1','РСА','РСОМ','РСЕ')
,('РЬ','РЯ','РЮ','N','1','РЯ','РЕМ','РЕ')
,('СЬ','СЯ','СЮ','N','1','СЯ','СЕМ','СЕ')
,('ТР','ТРА','ТРУ','N','1','ТРА','ТРОМ','ТРЕ')
,('ТЬ','ТЯ','ТЮ','N','1','ТЯ','ТЕМ','ТЕ')
,('УБ','УБА','УБУ','N','1','УБА','УБОМ','УБЕ')
,('УН','УНА','УНУ','N','1','УНА','УНОМ','УНЕ')
,('УП','УПА','УПУ','N','1','УПА','УПОМ','УПЕ')
,('УР','УРА','УРУ','N','1','УРА','УРОМ','УРЕ')
,('УЗ','УЗА','УЗУ','N','1','УЗА','УЗОМ','УЗЕ')
,('УС','УСА','УСУ','N','1','УСА','УСОМ','УСЕ')
,('ША','ШУ','ШЕ','N','1','ШУ','ШЕЙ','ШЕ')
,('ЫЙ','ОГО','ОМУ','N','1','ОГО','ЫМ','ОМ') --Серый как имя
,('ЫМ','ЫМА','ЫМУ','N','1','ЫМА','ЫМОМ','ЫМЕ')
,('ЫЧ','ЫЧА','ЫЧУ','N','1','ЫЧА','ЫЧЕМ','ЫЧЕ') --Сыч
,('ЯЗ','ЯЗА','ЯЗУ','N','1','ЯЗА','ЯЗОМ','ЯЗЕ')
,('ЯМ','ЯМА','ЯМУ','N','1','ЯМА','ЯМОМ','ЯМЕ')
,('ЯН','ЯНА','ЯНУ','N','1','ЯНА','ЯНОМ','ЯНЕ')
,('ЯР','ЯРА','ЯРУ','N','1','ЯРА','ЯРОМ','ЯРЕ')
,('ЯС','ЯСА','ЯСУ','N','1','ЯСА','ЯСОМ','ЯСЕ')
,('ЯТ','ЯТА','ЯТУ','N','1','ЯТА','ЯТОМ','ЯТЕ')
,('А','Ы','Е','N','2','У','ОЙ','Е')
,('ВЬ','ВИ','ВИ','N','2','ВЬ','ВЬЮ','ВИ')
,('ЕЯ','ЕИ','ЕЕ','N','2','ЕЮ','ЕЕЙ','ЕЕ')
--,('ИЯ','ИИ','ИЕ','N','2','ИЮ','ИЕЙ','ИЕ') --зульфиЯ /гульфиЯ/альфиЯ
,('ИЯ','ИИ','ИИ','N','2','ИЮ','ИЕЙ','ИИ')	--юлия/хулия/глория/лия
--,('ЛИЯ','ЛИИ','ЛИИ','N','2','ЛИЮ','ЛИЕЙ','ЛИЕ') --Юлии/АлиЕ/Азалии/САнии/СаниЕ/ГлОрии -- ударность ?
--справочник ударности окончаний в (женских) именах, и нижний регистр для безударных TODO
,('АЛИЯ','АЛИИ','АЛИЕ','N','2','АЛИЮ','АЛИЕЙ','АЛИЕ')
,('ЗАЛИЯ','ЗАЛИИ','ЗАЛИИ','N','2','ЗАЛИЮ','ЗАЛИЕЙ','ЗАЛИИ')
,('ФИЯ','ФИИ','ФИЕ','N','2','ФИЮ','ФИЁЙ','ФИЕ') --зульфиЯ /гульфиЯ/альфиЯ/э
,('ЛЯ','ЛИ','ЛЕ','N','2','ЛЮ','ЛЕЙ','ЛЕ')
,('НА','НЫ','НЕ','N','2','НУ','НОЙ','НЕ')
,('РЯ','РИ','РЕ','N','2','РЮ','РЕЙ','РЕ')
/*
'Карабас-Барабас-Бармалей Алия-Сания-Рея-Глория-Юлия-Гюльчатай Момыш-кызы-Петровна','и'
'Карабас-Барабас-Бармалей Алии-Сании-Реи-Глории-Юлии-Гюльчатай Момыш-кызы-Петровны','р'
'Карабас-Барабас-Бармалей Алию-Санию-Рею-Глорию-Юлию-Гюльчатай Момыш-кызы-Петровну','в'
'Карабас-Барабас-Бармалей Алие-Сание-Рее-Глорие-Юлие-Гюльчатай Момыш-кызы-Петровне','д'
'Карабас-Барабас-Бармалей Алией-Санией-Рей-Глорией-Юлией-Гюльчатай Момыш-кызы-Петровной','т'
'Карабас-Барабас-Бармалей Алие-Сание-Рее-Глорие-Юлие-Гюльчатай Момыш-кызы-Петровне','п'


*/
--,('УС','УСА','УСУ','N','2','УСА','УСОМ','УСЕ')
,('УЗ','УЗЫ','УЗЕ','N','2','УЗУ','УЗОЙ','УЗЕ')
,('ЬЯ','ЬИ','ЬЕ','N','2','ЬЮ','ЬЕЙ','ЬЕ')
,('ИЧ','ИЧА','ИЧУ','O','1','ИЧА','ИЧЕМ','ИЧЕ')
,('ОГЛЫ','ОГЛЫ','ОГЛЫ','O','1','ОГЛЫ','ОГЛЫ','ОГЛЫ')
,('КЫЗЫ','КЫЗЫ','КЫЗЫ','O','2','КЫЗЫ','КЫЗЫ','КЫЗЫ')
,('НА','НЫ','НЕ','O','2','НУ','НОЙ','НЕ')
,('БРАТ','БРАТА','БРАТУ','W','1','БРАТА','БРАТОМ','БРАТЕ')
,('ВНУК','ВНУКА','ВНУКУ','W','1','ВНУКА','ВНУКОМ','ВНУКЕ')
,('ДЕД','ДЕДА','ДЕДУ','W','1','ДЕДА','ДЕДОМ','ДЕДЕ')
,('ЗНАКОМЫЙ','ЗНАКОМОГО','ЗАКОМОМУ','W','1','ЗНАКОМОГО','ЗНАКОМЫМ','ЗНАКОМОМ')
,('ЗЯТЬ','ЗЯТЯ','ЗЯТЮ','W','1','ЗЯТЯ','ЗЯТЕМ','ЗЯТЕ')
,('МУЖ','МУЖА','МУЖУ','W','1','МУЖА','МУЖЕМ','МУЖЕ')
,('НАЧАЛЬНИК','НАЧАЛЬНИКА','НАЧАЛЬНИКУ','W','1','НАЧАЛЬНИКА','НАЧАЛЬНИКОМ','НАЧАЛЬНИКЕ')
,('ОТЕЦ','ОТЦА','ОТЦУ','W','1','ОТЦА','ОТЦОМ','ОТЦЕ')
,('ПАСЫНОК','ПАСЫНКА','ПАСЫНКУ','W','1','ПАСЫНКА','ПАСЫНКОМ','ПАСЫНКЕ')
,('ПОЛКОВНИК','ПОЛКОВНИКА','ПОЛКОВНИКУ','W','1','ПОЛКОВНИКА','ПОЛКОВНИКОМ','ПОЛКОВНИКЕ')
,('СВЕКР','СВЕКРА','СВЕКРУ','W','1','СВЕКРА','СВЕКРОМ','СВЕКРЕ')
,('СЫН','СЫНА','СЫНУ','W','1','СЫНА','СЫНОМ','СЫНЕ')
,('ТЕСТЬ','ТЕСТЯ','ТЕСТЮ','W','1','ТЕСТЯ','ТЕСТЕМ','ТЕСТЕ')
,('БАБКА','БАБКИ','БАБКЕ','W','2','БАБКУ','БАБКОЙ','БАБКЕ')
,('ВНУЧКА','ВНУЧКИ','ВНУЧКЕ','W','2','ВНУЧКУ','ВНУЧКОЙ','ВНУЧКЕ')
,('ДОЧЬ','ДОЧЕРИ','ДОЧЕРИ','W','2','ДОЧЬ','ДОЧЕРЬЮ','ДОЧЕРИ')
,('ЖЕНА','ЖЕНЫ','ЖЕНЕ','W','2','ЖЕНУ','ЖЕНОЙ','ЖЕНЕ')
,('ЗНАКОМАЯ','ЗНАКОМОЙ','ЗНАКОМОЙ','W','2','ЗНАКОМУЮ','ЗНАКОМОЙ','ЗНАКОМОЙ')
,('МАТЬ','МАТЕРИ','МАТЕРИ','W','2','МАТЬ','МАТЕРЬЮ','МАТЕРИ')
,('ПАДЧЕРИЦА','ПАДЧЕРИЦЫ','ПАДЧЕРИЦЕ','W','2','ПАДЧЕРИЦУ','ПАДЧЕРИЦЕЙ','ПАДЧЕРИЦЕ')
,('СВЕКРОВЬ','СВЕКРОВИ','СВЕКРОВИ','W','2','СВЕКРОВЬ','СВЕКРОВЬЮ','СВЕКРОВИ')
,('СЕСТРА','СЕСТРЫ','СЕСТРЕ','W','2','СЕСТРУ','СЕСТРОЙ','СЕСТРЕ')
,('СНОХА','СНОХИ','СНОХЕ','W','2','СНОХУ','СНОХОЙ','СНОХЕ')
,('ТЕЩА','ТЕЩИ','ТЕЩЕ','W','2','ТЕЩУ','ТЕЩЕЙ','ТЕЩЕ')
) as t  (Z, RP, DP, TIP, POL, VP, TP, PP)
		) t
		WHERE t.pol=p_POL
		AND t.tip=p_WType
		ORDER BY length(t.z) DESC;
		
	fio_ record;

	-- флаг, сигнализирующие, что окончание найдено
	found_flag BOOLEAN:=FALSE;
	-- для хранения длины окончания из таблицы FIO
	lzw INTEGER:=0;
	-- для хранения длины слова
	lw INTEGER;
	-- для хранения результатов склонения
	newz_w varchar(55);
	-- для хранения окончания исходного слова
	cut varchar(50);
	v_padOutUp text:= Upper(p_PadOut);
	p_choice boolean := upper (p_Word)=p_Word;
	v_pfx text :='';
BEGIN
	--p_Word:=upper (p_Word);
	-- Получим длину Ф., И., О., переданных через параметры
	lw :=length(p_Word);
	raise notice 'p_Word: % ,%,%,%' ,  p_Word::text, p_WType,p_POL,p_PadOut;
	FOR fio_ IN cs1 LOOP
		
		lzw :=length(fio_.z);
		IF NOT(lw<lzw) THEN -- (#3) сравнение длины фамилии и окончания
			--cut:=substr(p_Word, (lw-lzw)+1);
			
			cut:=UPPER(right(p_Word,lzw));
			IF (cut=fio_.z) THEN	-- (#4) если окончание найдено
				raise notice '% ' ,  fio_::text;
				found_flag:=TRUE; -- то установим флаг
				-- и отрежем от фамилии окончание
				--newz_w:=substr(p_Word, 1, (lw-lzw));
				newz_w:=left(p_Word,(lw-lzw));
				-- Подставляем окончание, соответствующее склонению
				CASE v_padOutUp
				WHEN 'ROD' THEN -- (#5)
					v_pfx:=fio_.rp;
				WHEN 'DAT' THEN
					v_pfx:=fio_.dp;
				WHEN 'VIN' THEN
					v_pfx:=fio_.vp;
				WHEN 'TVOR' THEN
					v_pfx:=fio_.tp;
				WHEN 'PRED' THEN
					v_pfx:=fio_.pp;
				ELSE
					found_flag:=FALSE;
				END CASE; -- (#5)
				if found_flag then
					if p_choice THEN
					elsif v_pfx<>'' THEN
						v_pfx:=lower(v_pfx);
					END if;
					newz_w:=CONCAT(newz_w ,v_pfx);
				end if;
				
				EXIT; -- прекращаем поиск окончаний
				
			END IF; -- (#4)
		END IF; -- (#3) конец сравнения длины фамилии и окончания

	END LOOP;
	-- если окончание найдено, то возвращаем слово, иначе NULL
	IF found_flag=TRUE THEN
		RETURN(newz_w);
	ELSE
		--RETURN(NULL);
		RETURN p_Word;
	END IF;
END;
$$;
create or replace function ora_padej_fio(
		IN p_fio text			-- ФИО
		,IN p_padzh text		-- падеж: 'р'|'Р'|'2'-родительный,'д'|'Д'|'3'-дательный,
												-- 'в'|'В'|'4'-винительный,'т'|'Т'|'5'-творительный,
												-- 'п'|'П'|'6'-предложный
		,IN p_fio_fmt text DEFAULT 'ФИО' -- формат ФИО: 'Алексей Немов'->'ИФ',
																 -- 'Ольга Львовна Гидова-Бережная'->'ИОФ'
		,IN p_sex text DEFAULT null -- пол: 'ж'|'Ж'|'м'|'М'
	) returns text
language plpgsql immutable 
AS $$
--TODO валидацию, разбор неопределенных случаев секаса пола 
--и остапов-бендер-мария-ххххх--беев (кто на ком стоял)
declare
	a_Word		text[];
	a_WType	char[];
	p_POL		int;
	p_PadOut	text;
	_res text;
begin
	a_Word := string_to_array(regexp_replace(regexp_replace(p_fio,'\s*\-\s*',chr(7),'ig')
													,'[\.\s]+',' ','ig'),' ');--save replaced tokenz ?
	a_WType := array_agg(
					CASE u 
					WHEN 'Ф' THEN 'F'
					WHEN 'И' THEN 'N'
					WHEN 'О' THEN 'O'
					WHEN 'П' THEN 'P'
					END 
					order by ord) from
				unnest (string_to_array(trim(p_fio_fmt),null)) with ordinality AS u(u,ord) ;
	p_POL := CASE upper(p_sex) 
			WHEN 'М' THEN 1
			WHEN 'Ж' THEN 2
			ELSE 0
			END;
	p_PadOut := CASE p_padzh
				WHEN 'и'	THEN 'IM'
				WHEN 'И'	THEN 'IM'
				WHEN '1'	THEN 'IM'
				WHEN 'р'	THEN 'ROD'
				WHEN 'Р'	THEN 'ROD'
				WHEN '2'	THEN 'ROD'
				WHEN 'д'	THEN 'DAT'
				WHEN 'Д'	THEN 'DAT'
				WHEN '3'	THEN 'DAT'
				WHEN 'в'	THEN 'VIN'
				WHEN 'В'	THEN 'VIN'
				WHEN '4'	THEN 'VIN'
				WHEN 'т'	THEN 'TVOR'
				WHEN 'Т'	THEN 'TVOR'
				WHEN '5'	THEN 'TVOR'
				WHEN 'п'	THEN 'PRED'
				WHEN 'П'	THEN 'PRED'
				WHEN '6'	THEN 'PRED'
				END;
	_res := string_agg( CASE WHEN w ~ chr(7) THEN
							(SELECT string_agg(ora_padej(ww, wt,p_POL ,p_PadOut )
								,'-' order by ordw)
							
							FROM unnest(string_to_array(w,chr(7)))
							WITH ordinality AS un(ww,ordw)
							)
						else
							ora_padej(w, wt,p_POL ,p_PadOut )
						end
						,' ' order by ord )
						
	FROM unnest(a_WType) with ordinality AS u(wt,ord)
	LEFT JOIN LATERAL unnest (a_Word ) with ordinality AS uw(w,ord) using(ord) ;
	RETURN _res;
end;
$$;

/*
SELECT ora_padej('Путин Владимир Владимирович', 'F',1 ,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Гондурас-Чеши Громозекас Хозеевич', 'F',1 ,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Гондурас-Болеславская Громозекас Хоевна', 'F',1,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Хуан Хуанович Рохас-Кастильо','F',1,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Хуан Хуанович Рохас-Кастильо','F',1,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Гомаюн Ярослав Кузьмич','F',1,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Кузьмич Фаина Ярославна','F',1,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Кузьмич Фаина Ярославна','F',1,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
UNION all SELECT 
	ora_padej('Кузьмич Фаина Ярослав беге','F',1,p ),p FROM unnest(array['ROD','DAT','VIN','TVOR','PRED']) u(p)
	;
*/

SELECT ora_padej_fio('Путин Владимир Владимирович', p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Перес -Палех Андреас Хозеевич', p,'ФИО','м'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)

UNION all SELECT 
	ora_padej_fio('Гондурас-Чеши Арбуз Хозеевич', p,'ФИО','м'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Гондурас-Болеславская Медея - Анна -Аргуз Хоревна', p,'ФИО','ж'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Хуан Хуанович Рохас-Кастильо', p,'ИОФ','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Хуана Хуановна Хуанович-Рохас-Кастильо', p,'ИОФ','ж' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Гомон Ярослав Кузьмич', p,'ФИО' ,'м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Кузьмич Фаина Ярославна',p,'ФИО','ж' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Кузьмич-Ильич-Кащей Лич-Серый-Сыч Янусович',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Кузьмич Фаина Ярослав-беге',p,'ФИО','ж'  ),p FROM unnest(array['и','р','в','д','т','п','1','2','3','4']) u(p)
UNION all SELECT 
	ora_padej_fio('Карабас-Барабас-Бармалей Оглы-Бей Момыш-Улы',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
--Алия,Сания,Асия 
UNION all SELECT 
	ora_padej_fio('Карабас-Барабас-Бармалей Алия-Сания- Рея-Лорелея-Галерея-Галера-Холера -Глория -Юлия- Гюльчатай Момыш-кызы-Петровна',p,'ФИО','ж' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
--какучия гиви
UNION all SELECT 
	ora_padej_fio('Берия-Какучия-Могучая-Кипиани-Самошвали-Руставели-Шенгелия-Джугашвили Алия-Сания- Гиви Резоевич',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
UNION all SELECT 
	ora_padej_fio('Вуячкявичус-Вуячич Вуячич-Вуяч Вуячиевич',p,'ФИО','м' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
UNION all SELECT 
	ora_padej_fio('Вуячкявичене-Вуячич Вуячич-Вуяч Вуячиевна',p,'ФИО','ж' ),p FROM unnest(array['и','р','в','д','т','п']) u(p)
;



наташу ещё можно пощупать, наверное, если искать и пересклонёвывать в произвольных местах текста. https://github.com/natasha/yargy
https://github.com/natasha/natasha
но её прикручивать снаружи. она на пайморфе базюкается.
...
Рейтинг: 0 / 0
19.02.2018, 12:24
    #39604077
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
Author the new onePG81,

Довольно давно делал склонение эвристически (по отчеству определяем пол, далее тупо перечисляем варианты - мужик, фамилии на "- ОВ/ИН/МАН/ШТЕЙН/твердый согласный" => "||У", "-ИЙ" => "ОМУ" и т.п. ) на TSQL. Всех дел часа на два при наличии хорошего списка ФИО. Затыкалось реально на чем-то вроде Ли Сын Ман, Пу И или Уильям Генри Гейтс - ну там и так непонятно, как склонять.

Вайнштейн-ий Харрасментов
...
Рейтинг: 0 / 0
19.02.2018, 15:38
    #39604308
Ы2
Ы2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
Ролг ХупинAuthor the new onePG81,

Довольно давно делал склонение эвристически (по отчеству определяем пол, далее тупо перечисляем варианты - мужик, фамилии на "- ОВ/ИН/МАН/ШТЕЙН/твердый согласный" => "||У", "-ИЙ" => "ОМУ" и т.п. ) на TSQL. Всех дел часа на два при наличии хорошего списка ФИО. Затыкалось реально на чем-то вроде Ли Сын Ман, Пу И или Уильям Генри Гейтс - ну там и так непонятно, как склонять.

Вайнштейн-ий Харрасментов
С точки зрения алгоритма, это то же, что и Юрий Иванов.
...
Рейтинг: 0 / 0
19.02.2018, 20:21
    #39604436
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Склонение ФИО в postgres как сделать?
Ы2Ролг Хупинпропущено...


Вайнштейн-ий Харрасментов
С точки зрения алгоритма, это то же, что и Юрий Иванов.
вонавИ йирЮ != вотнемсарраХ йи-нйетшнйаВ

в алгоритмах проблема с выявлением ударности гласных.

и первая, с "ё" наё, (хотя я там пару мест недочистил -- возможно и тут пропустил). а второй -- скорее подход, чем решение. там надо сито правил вешать на поток "сырого данного", и отжимать минимальные, покрывающие. уж очень рыхлая паковка.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Склонение ФИО в postgres как сделать? / 12 сообщений из 12, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]