Разделение двойного символа среднего инициала с использованием выражения CASE в хранимой процедуре SQL Server - PullRequest
0 голосов
/ 03 октября 2019

Например: вместо «Хуан Дела Крус Эудженио» стать «Хуан Округ. Эудженио»

The expected flow

Моя попытка:

SELECT
(
    UPPER(lastName) 
    + ', '
    +UPPER(SUBSTRING(firstName,1,1)) + LOWER(SUBSTRING(firstName,2,99))
    +' '
    +Suffix
    +' '
    +(
        case
            when tb_persons.middleName = '' or tb_persons.middleName = ' ' or tb_persons.middleName is null
            then ''
            else
            UPPER(SUBSTRING(tb_persons.middleName,1,1))+'.'
        end)
) as name,
UPPER(SUBSTRING(firstName,1,1)) + LOWER(SUBSTRING(firstName,2,99)) as 'firstName',
UPPER(lastName) as 'lastName',middleName

FROM tb_persons

Ответы [ 3 ]

2 голосов
/ 03 октября 2019

Поскольку вы не ответили на мой комментарий, и до этого есть два способа решения этой проблемы (в зависимости от того, что вы предоставляете)

  • Метод 1:

    SELECT CONCAT(
                   PARSENAME(REPLACE(Name, ' ', '.'), 4),
                   ' ',
                   SUBSTRING(PARSENAME(REPLACE(Name, ' ', '.'), 3), 1, 1),
                   SUBSTRING(PARSENAME(REPLACE(Name, ' ', '.'), 2), 1, 1),
                   '.',
                   PARSENAME(REPLACE(Name, ' ', '.'), 1) 
                 )
    FROM
    (
      VALUES
      ('Juan Dela Cruz Eugenio')
    ) T(Name)
    
  • Метод 2

    SELECT STRING_AGG( CASE RN WHEN 2 THEN SUBSTRING(V, 1, 1)
                               WHEN 3 THEN SUBSTRING(V, 1, 1)
                               WHEN 4 THEN '.' + V
                       ELSE V + ' ' END, ''
                     )
    FROM
    (
      VALUES
      (1, 'Juan Dela Cruz Eugenio')
    ) T(Id, Name) CROSS APPLY
    (
      SELECT Value, ROW_NUMBER() OVER(ORDER BY Id) RN
      FROM STRING_SPLIT(Name, ' ')
    ) TT(V, RN)
    GROUP BY Id
    

Онлайн-демонстрация

1 голос
/ 03 октября 2019

Вам уже говорили, что работа с именами может быть очень хитрой ...

Вы можете попробовать что-то подобное:

- A mockup-sceanrio смоделировать вашу проблему

DECLARE @mockupTable TABLE(ID INT IDENTITY, YourNameString VARCHAR(1000));
INSERT INTO @mockupTable VALUES
 ('Juan Dela Cruz Eugenio')
,('Jhon Lester')
,('Jhon MiddleName Lester')
,('Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso'); 

- Запрос

SELECT castedAndSplit.value('/x[1]','nvarchar(100)') AS FirstName
      ,CASE castedAndSplit.value('count(/x)','int') WHEN 1 THEN ''
                                                    WHEN 2 THEN ''  
                                                    WHEN 3 THEN CONCAT(castedAndSplit.value('substring(/x[2],1,1)','nchar(1)')
                                                                      ,'.')
                                                    ELSE        CONCAT(castedAndSplit.value('substring(/x[2],1,1)','nchar(1)')
                                                                      ,castedAndSplit.value('substring(/x[3],1,1)','nchar(1)')
                                                                      ,'.') END AS MiddleName
      ,castedAndSplit.value('/x[last()]','nvarchar(100)') AS LastName
FROM @mockupTable t
CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT t.YourNameString AS [*] FOR XML PATH('')),' ','</x><x>')+ '</x>' AS XML)) A(castedAndSplit);

Результат

FirstName   MiddleName  LastName
Juan        DC.         Eugenio
Jhon                    Lester
Jhon        M.          Lester
Pablo       DJ.         Picasso

Подсказка: объединить три в одном легко, я оставляюэто до вас ...

Идея вкратце:

С помощью хитрости, использующей некоторые замены строк, мы можем преобразовать строку в XML, где каждый фрагмент взят отдельно.

Теперь мы можем выбрать первый и последний элемент и взять их как FirstName и LastName.

Для MiddleName мы можем использовать количество фрагментов. 1 или 2 фрагмента не будут иметь отчества, 3 фрагмента будут иметь одно имя посередине, а любой счетчик выше 3 будет использовать 2-й и 3-й фрагменты инициала.

0 голосов
/ 03 октября 2019

Просто еще один вариант для развлечения, если вы не возражаете против вспомогательной функции.

Спасибо Shnugo за образец данных и смешное имя (которое я редактировал) + 1

FYI - TVF можно легко перенести в CROSS APPLY

Пример

DECLARE @mockupTable TABLE(ID INT IDENTITY, YourNameString VARCHAR(1000));
INSERT INTO @mockupTable VALUES
 ('Juan Dela Cruz Eugenio')
,('Jhon Lester')
,('Jhon MiddleName Lester')
,('Pablo Diego José Francisco de Paula Juan Nepomuceno Picasso'); 


Select A.*
      ,FirstName  = Pos1
      ,MiddleInit = concat(nullif(
                    concat( left(Pos2+Pos3,1)
                           ,left(Pos3+Pos4,1)
                           ,left(Pos4+Pos5,1)
                           ,left(Pos6+Pos7,1)
                           ,left(Pos7+Pos8,1)
                           ,left(Pos8+Pos9,1)
                          )
                    ,'')+'.','')
      ,LastName   = coalesce(Pos9,Pos8,Pos7,Pos6,Pos5,Pos4,Pos3,Pos2)
 From  @mockupTable A
 Cross Apply [dbo].[tvf-Str-Parse-Row](YourNameString,' ') B

Возвращает

enter image description here

Функция, если интересно

ALTER FUNCTION [dbo].[tvf-Str-Parse-Row] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (
    Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
          ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
          ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
          ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
          ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
          ,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
          ,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(max)')))
          ,Pos8 = ltrim(rtrim(xDim.value('/x[8]','varchar(max)')))
          ,Pos9 = ltrim(rtrim(xDim.value('/x[9]','varchar(max)')))
    From  ( values (cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml))) as A(xDim)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...