Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
black_sql
Member

Откуда:
Сообщений: 52
Зада простая в одном поле есть Фамилия Имя Отчество для печати надо получить Фамилию И. О.
Кто решал подобную задачу, может, есть решение по лучше?

declare @name nvarchar (128), @pf int, @ps int
select @name = 'Иванов Сергей Петрович'

select ISNULL(CASE CHARINDEX(' ', LTRIM(@name)) WHEN 0 THEN LTRIM(@name) END, 
       SUBSTRING(LTRIM(@name), 1, CHARINDEX(' ', LTRIM(@name))) + ' ' +
       CASE LEN(SUBSTRING(LTRIM(SUBSTRING(LTRIM(@name), LEN(SUBSTRING(LTRIM(@name), 1, CHARINDEX(' ', LTRIM(@name)))) + 1, len(LTRIM(@name)))), 1, 1)) WHEN 0 THEN '' ELSE SUBSTRING(LTRIM(SUBSTRING(LTRIM(@name), LEN(SUBSTRING(LTRIM(@name), 1, CHARINDEX(' ', LTRIM(@name)))) + 1, len(LTRIM(@name)))), 1, 1) + '. ' END + 
       CASE LEN(SUBSTRING(LTRIM(SUBSTRING (LTRIM(SUBSTRING(LTRIM(@name), LEN(SUBSTRING(LTRIM(@name), 1, CHARINDEX(' ', LTRIM(@name)))) + 1, len(LTRIM(@name)))), CHARINDEX(' ', LTRIM(SUBSTRING(LTRIM(@name), LEN(SUBSTRING(LTRIM(@name), 1, CHARINDEX(' ', LTRIM(@name)))) + 1, len(LTRIM(@name))))), len(LTRIM(@name)))), 1, 1)) WHEN 0 THEN '' ELSE SUBSTRING(LTRIM(SUBSTRING (LTRIM(SUBSTRING(LTRIM(@name), LEN(SUBSTRING(LTRIM(@name), 1, CHARINDEX(' ', LTRIM(@name)))) + 1, len(LTRIM(@name)))), CHARINDEX(' ', LTRIM(SUBSTRING(LTRIM(@name), LEN(SUBSTRING(LTRIM(@name), 1, CHARINDEX(' ', LTRIM(@name)))) + 1, len(LTRIM(@name))))), len(LTRIM(@name)))), 1, 1) + '.' END)
10 дек 08, 14:20    [6550734]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 36800
А петрова-водкина схавает?
10 дек 08, 14:21    [6550743]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Taffy
Member

Откуда:
Сообщений: 20498
black_sql
Зада простая в одном поле есть Фамилия Имя Отчество

А нормальной формы данных нет? Чтобы отдельно фамилия, отдельно имя, отдельно отчество?
10 дек 08, 14:37    [6550900]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Anddros
Member

Откуда:
Сообщений: 1077
select parsename(replace(@name,' ','.'),3)+' '+
 left(parsename(replace(@name,' ','.'),2),1)+'. '+
 left(parsename(replace(@name,' ','.'),1),1)+'.'
10 дек 08, 14:41    [6550931]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
select substring(nam,1,p1-1)+' '+substring(nam,p1+1,1)+'.'+substring(nam,p2+1,1) +'.'
from (
select @name as nam, charindex(' ',@name) as p1, charindex(' ',@name,charindex(' ',@name)+1) as p2
) a

далее возникают неприятные вопросы о возможности сдвоенных пробелов и наличии пробелов внутри фамилии/имени (Мельников - Печерский Али - Мухамед Иванович). Лучше всего разобрать это по словам через CTE, а потом тонко анализировать такие глупости.
10 дек 08, 14:42    [6550939]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
Разбор можно делать примерно так
declare @str varchar(128)
set @str='Мельников - Печерский Али - Мухамед Иванович';
IF OBJECT_ID('tempdb..#words') IS NOT NULL drop table #words;
with ProcessText (startPos, spacePos) as (
select 1 as startPos, charindex(' ',@str,1) as spacePos
union all
select spacePos+1, charindex(' ',@str,spacePos+1)
from ProcessText where spacePos > 0)
select startPos, spacePos, substring(@str,startPos,spacePos-startPos) as singleWord
into #words from ProcessText where spacePos <> 0
union all
select max(spacePos)+1,0,right(@str,len(@str)-max(spacePos))
from ProcessText
option (maxrecursion 0);
select * from #words;

дальнейшие заморочки с таблицей #words не привожу, поскольку вариантов имен и ошибок при их написании довольно много. Например, "О' Коннор Н' гомо робертович"
10 дек 08, 14:58    [6551088]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Не пугайтесь...
DECLARE @S VARCHAR(100), @Delimiters VARCHAR(100);
SET @Delimiters=CHAR(10)+CHAR(13)+CHAR(9)+',.; :=';
SET @S='Петров-Водкин Кузьма Сергеевич';
SELECT
 STUFF
 (
  (
   SELECT ' '+CASE N WHEN 1 THEN S ELSE LEFT(S,1)+'.' END FROM
   (
    SELECT ROW_NUMBER()OVER(ORDER BY V.number), SUBSTRING(@S,V.number,
     (
      SELECT MIN(VV.number)
      FROM master.dbo.spt_values VV
      WHERE VV.type='P' AND VV.number BETWEEN V.number AND LEN(@S)+1
      AND SUBSTRING(@S+LEFT(@Delimiters,1),VV.number,1) LIKE '['+@Delimiters+']'
     )-V.number
    )
    FROM master.dbo.spt_values V
    WHERE V.type='P' AND V.number BETWEEN 1 AND LEN(@S)+1
    AND SUBSTRING(LEFT(@Delimiters,1)+@S,V.number,1) LIKE '['+@Delimiters+']'
   ) T(N,S)
   WHERE S>''
   ORDER BY N
   FOR XML PATH('')
  ),1,1,''
 );

Зато можно задать любые разделители, которые могут стоять где угодно в строке в любом количестве.
10 дек 08, 15:13    [6551230]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
iap
Не пугайтесь...
DECLARE @S VARCHAR(100), @Delimiters VARCHAR(100);
SET @Delimiters=CHAR(10)+CHAR(13)+CHAR(9)+',.; :=';
SET @S='Петров-Водкин Кузьма Сергеевич';
SELECT
 STUFF
 (
  (
   SELECT ' '+CASE N WHEN 1 THEN S ELSE LEFT(S,1)+'.' END FROM
   (
    SELECT ROW_NUMBER()OVER(ORDER BY V.number), SUBSTRING(@S,V.number,
     (
      SELECT MIN(VV.number)
      FROM master.dbo.spt_values VV
      WHERE VV.type='P' AND VV.number BETWEEN V.number AND LEN(@S)+1
      AND SUBSTRING(@S+LEFT(@Delimiters,1),VV.number,1) LIKE '['+@Delimiters+']'
     )-V.number
    )
    FROM master.dbo.spt_values V
    WHERE V.type='P' AND V.number BETWEEN 1 AND LEN(@S)+1
    AND SUBSTRING(LEFT(@Delimiters,1)+@S,V.number,1) LIKE '['+@Delimiters+']'
   ) T(N,S)
   WHERE S>''
   ORDER BY N
   FOR XML PATH('')
  ),1,1,''
 );

Зато можно задать любые разделители, которые могут стоять где угодно в строке в любом количестве.


Все одно на пробелы в фамилии реагирует нервно, но разнообразно. Попробуйте варианты:
'Петров- Водкин Кузьма Сергеевич'
'Петров -Водкин Кузьма Сергеевич'
'Петров - Водкин Кузьма Сергеевич'
получите удовольствие.
10 дек 08, 15:27    [6551366]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Слегка поправлю (а то если строка начинается с разделителя, то работает неправильно)
DECLARE @S VARCHAR(100), @Delimiters VARCHAR(100);
SET @Delimiters=CHAR(10)+CHAR(13)+CHAR(9)+',.; :=+';
SET @S='=Петров-Водкин.=,,, Кузьма++	;;: Сергеевич,...';
SELECT
 STUFF
 (
  (
   SELECT ' '+CASE ROW_NUMBER()OVER(ORDER BY N) WHEN 1 THEN S ELSE LEFT(S,1)+'.' END FROM
   (
    SELECT V.number, SUBSTRING(@S,V.number,
     (
      SELECT MIN(VV.number)
      FROM master.dbo.spt_values VV
      WHERE VV.type='P' AND VV.number BETWEEN V.number AND LEN(@S)+1
      AND SUBSTRING(@S+LEFT(@Delimiters,1),VV.number,1) LIKE '['+@Delimiters+']'
     )-V.number
    )
    FROM master.dbo.spt_values V
    WHERE V.type='P' AND V.number BETWEEN 1 AND LEN(@S)+1
    AND SUBSTRING(LEFT(@Delimiters,1)+@S,V.number,1) LIKE '['+@Delimiters+']'
   ) T(N,S)
   WHERE S>''
   ORDER BY N
   FOR XML PATH('')
  ),1,1,''
 );
Выглядит, конечно, монструозно.
10 дек 08, 15:30    [6551389]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
remi_,

а зачем же в середину фамилии разделители вставлять? Это нечестно!
10 дек 08, 15:32    [6551400]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
sander1
Member

Откуда: Москва
Сообщений: 366
Недавно решал ту же задачу, и натолкнулся на еще одно исключение. В азербайджане (и, как выяснилось, других тюркоязычных странах) часто отчество формируется через имя + "Оглы" (муж.) или "Кызы" (жен.). Пишется как я понимаю обычно через пробел.
10 дек 08, 17:45    [6552686]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
sander1,

IMHO, Оглы пишется через дефис.
10 дек 08, 19:49    [6553372]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
iap
sander1,

IMHO, Оглы пишется через дефис.
http://www.gramota.ru/spravka/buro/search_answer/?s=%EE%E3%EB%FB
10 дек 08, 20:07    [6553412]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Гата Селов
Member

Откуда:
Сообщений: 433
iap,
в Российских паспортах оглы и кызы чащ всего пишется с маленькой буквы через пробел. Видел также с бльшой буквы через пробел. Видел и через дефис. Так что кправила тут не действуют
10 дек 08, 23:43    [6553842]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
black_sql
Member

Откуда:
Сообщений: 52
Taffy
black_sql
Зада простая в одном поле есть Фамилия Имя Отчество

А нормальной формы данных нет? Чтобы отдельно фамилия, отдельно имя, отдельно отчество?


Естественно нет...
11 дек 08, 09:26    [6554333]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
black_sql
Member

Откуда:
Сообщений: 52
Гавриленко Сергей Алексеевич
А петрова-водкина схавает?


Из 'Петрова-водкина Людмила Сергеевна' - > Петрова-водкина Л. С.
11 дек 08, 09:28    [6554338]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
black_sql
Member

Откуда:
Сообщений: 52
Anddros
select parsename(replace(@name,' ','.'),3)+' '+
 left(parsename(replace(@name,' ','.'),2),1)+'. '+
 left(parsename(replace(@name,' ','.'),1),1)+'.'


Красиво но если есть лишние пробелы, то сразу возникаю проблемы, а пробелы есть...
11 дек 08, 09:35    [6554360]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Anddros
Member

Откуда:
Сообщений: 1077
black_sql
Anddros
select parsename(replace(@name,' ','.'),3)+' '+
 left(parsename(replace(@name,' ','.'),2),1)+'. '+
 left(parsename(replace(@name,' ','.'),1),1)+'.'


Красиво но если есть лишние пробелы, то сразу возникаю проблемы, а пробелы есть...

Если только пробелы, то нет проблем:

select parsename(name,3)+' '+left(parsename(name,2),1)+'. '+left(parsename(name,1),1)+'.'
from (select name=replace(replace(replace(@name,'   ',' '),'  ',' '),' ','.'))ttt
Нормально работает при количестве пробелов до 4.
Если добавить еще всего один внутренний replace (c 4 пробелов на 1), то будет кушать уже до 10 пробелов кряду. Ну и т.д.
11 дек 08, 13:29    [6556150]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Anddros
Нормально работает при количестве пробелов до 4.
Если добавить еще всего один внутренний replace (c 4 пробелов на 1), то будет кушать уже до 10 пробелов кряду. Ну и т.д.
Удаление лишних пробелов из строки
11 дек 08, 13:58    [6556393]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
BorisPlus
Member

Откуда:
Сообщений: 43
Всем привет и сразу к делу)
Есть недобросовестно заполненная база, где в текстовых полях встречается и несколько (от 2 до 30) пробелов подряд, и несколько запятых и вообще много чего "малдаванского", видимо они и заполняли.
Я так понимаю, средствами MSSQL такой задачки не решить (хотя б пробелы убрать и запятые) и необходимо писать что-то свое. В Оракле можно было б поиграть с регулярками. Записей пока не много - около 4 000 000.
Так вот - есть ли уже какие готовые продукты по искоренению этого зла? Я пока не говорю о правописании, а только о синтаксисе.
20 июл 09, 22:44    [7437793]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Senya_L
Member

Откуда: Москва
Сообщений: 5381
BorisPlus
Всем привет и сразу к делу)
Есть недобросовестно заполненная база, где в текстовых полях встречается и несколько (от 2 до 30) пробелов подряд, и несколько запятых и вообще много чего "малдаванского", видимо они и заполняли.
Я так понимаю, средствами MSSQL такой задачки не решить (хотя б пробелы убрать и запятые) и необходимо писать что-то свое. В Оракле можно было б поиграть с регулярками. Записей пока не много - около 4 000 000.
Так вот - есть ли уже какие готовые продукты по искоренению этого зла? Я пока не говорю о правописании, а только о синтаксисе.
Пробелы - это единственная беда?
20 июл 09, 23:19    [7437836]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Senya_L
Member

Откуда: Москва
Сообщений: 5381
Senya_L
Пробелы - это единственная беда?
Поправлюсь. Хотел сказать: "Пробелы и запятые - это единственная проблема?". Если так, то...
BorisPlus
Всем привет и сразу к делу)
Угу. Здорово.
автор
Я так понимаю, средствами MSSQL такой задачки не решить
Откуда такое убеждение? Или предубеждение?
автор
В Оракле можно было б поиграть с регулярками.
Вы мне ответьте, будь ласка, снобизм и чванство - это ораклятая привычка усих ораклистов? Если уж пришли на форум по MSSQL с вопросом, то выеживаться-то не стОит, имхо.
автор
(хотя б пробелы убрать и запятые)
Что мешает заменить запятые на пробелы стандартной функцией REPLACE? А дальше по рекомендациям в этом топике и многих других.
20 июл 09, 23:41    [7437876]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
Senya_L
Member

Откуда: Москва
Сообщений: 5381
Пример
USE [tempdb]
GO

DECLARE @tbl TABLE([name] VARCHAR(60))

INSERT INTO @tbl ([name])
SELECT 'Иванов,            Иван          Иванович' UNION ALL
SELECT 'Петров-Водкин,,    Кузьма  ,  Сергеевич'

		SELECT
			UPPER(REPLACE(Q.[fio], '.', ' ')) AS fio,
			PARSENAME(Q.[fio], 3) AS [Surname],
			PARSENAME(Q.[fio], 2) AS [Name],
			PARSENAME(Q.[fio], 1) AS [Secname]
		FROM (
			SELECT
				REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(RTRIM(LTRIM(UPPER(
					CASE 
						WHEN SUBSTRING([Name], LEN([Name]), 1) = '.' THEN SUBSTRING([Name], 1, LEN([Name]) - 1)
						ELSE [Name]
					END))), ',', ' '), '  ', ' '), '  ', ' '), '  ', ' '), '  ', ' '), ' ', '.') AS fio
			FROM @tbl T
			WHERE [Name] IS NOT NULL
		) Q
GO
20 июл 09, 23:55    [7437894]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
BorisPlus
В Оракле можно было б поиграть с регулярками.
Если очень хочется, то
http://blogs.msdn.com/khen1234/archive/2005/05/11/416392.aspx
http://blogs.msdn.com/khen1234/archive/2005/05/19/420209.aspx
Не так просто, как в Oracle, но на безрыбье, как говорится...
Вот только в рамках описанных проблем это стрельба из пушки по воробьям. IMHO
21 июл 09, 09:07    [7438282]     Ответить | Цитировать Сообщить модератору
 Re: Кто лучше? (Фамилия Имя Отчество - > Фамилия И. О. )  [new]
BorisPlus
Member

Откуда:
Сообщений: 43
Senya_L
Откуда такое убеждение? Или предубеждение?

Разубедите меня, если это так просто.
Senya_L
Вы мне ответьте, будь ласка, снобизм и чванство - это ораклятая привычка усих ораклистов? Если уж пришли на форум по MSSQL с вопросом, то выеживаться-то не стОит, имхо.

Никто и не выеживается, уважаемый, просто я пробовал решать задачи с исправлением текстовых данных с помощью регулярок, и не только непосредственно Оракловскими. Регулярные выражения, я считаю, весьма изящное решение, хотя и ресурсоемкое, но все таки оно "выглядит красивее", чем некоторое число вложенных реплейсов и/или циклов, хотя кому как...
Senya_L
Что мешает заменить запятые на пробелы стандартной функцией REPLACE?

Задача на самом деле поглубже, простите, что с самого начала не полно сформулировал:
"Есть недобросовестно заполненная база, где в текстовых полях встречается и несколько (от 2 до 30) пробелов подряд, и несколько запятых и вообще много чего "малдаванского", видимо они и заполняли. Записей пока не много - около 4 000 000.Так вот - есть ли уже какие готовые продукты по искоренению этого зла? Я пока не говорю о правописании отдельных слов в падежах, а только о синтаксисе."

Странно, Senya_L, я и не думал выеживаться...на форум к вам и пришел, что MSSQL пока мне до одного места и нужно решить эту задачу быстро, а потом уже думать...Простите, сам понимаю, что глупо, но именно так и надо сейчас...Возможности перенести базу пока не имеется, утилиту (процедуру) исправления необходимо запустить именно с этого компа...

Ладно, раз не встречалось ничего готового бесплатного и толкового, то не встречалось...
Всем спасибо
21 июл 09, 18:15    [7441971]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить