SQL-получить подстроку после первого пробела и второго пробела в отдельных столбцах

У меня есть столбец FullName, содержащий FirstName, MiddleName, LastName.
Например:

Полное имя: Мэрилин Кин Киркленд

Я хочу иметь 3 отдельных столбца для FirstName, MiddleName и LastName из FullName, взяв из него подстроку.

Я вытягиваю FirstName, используя код:

substring(c.LegalName, 1, CHARINDEX(' ', c.LegalName)) as 'First Name'

Мне интересно, как я могу получить только отчество, которое идет после первого пробела и перед вторым пробелом?
Кроме того, я хочу получить фамилию, которая идет после второго пробела?


person Geetanjali Sachdeva    schedule 01.04.2015    source источник
comment
Это плохая идея. Не в каждом полном имени есть два пробела, а в тех, которые есть, не все состоят из имени, отчества и фамилии. (Не у всех есть отчество (или даже фамилия); у многих людей несколько имен/отцов/фамилий; имя/отчество/фамилия могут содержать пробелы; за фамилией могут следовать дополнительные суффиксы; и т. д. и т. п. и т. д.) См. w3.org/International/questions/qa-personal-names. .   -  person ruakh    schedule 01.04.2015
comment
CHARINDEX имеет третий параметр. Используй это.   -  person GSerg    schedule 01.04.2015
comment
@ruakh Я знаю, что это плохая идея, но наш клиент хочет, чтобы данные выглядели именно так. Знаете ли вы, как я могу вытащить отчество, которое идет после первого пробела и перед вторым пробелом, и вытащить фамилию, которая идет после второго пробела? Если нет отчества или фамилии, его следует оставить пустым. Ваша помощь будет оценена по достоинству.   -  person Geetanjali Sachdeva    schedule 01.04.2015
comment
@GeetanjaliSachdeva: Ваш клиент нанял вас благодаря вашему опыту. Если вы знаете, что что-то является плохой идеей, то ваш клиент должен извлечь пользу из этого знания. Вы должны объяснить ему/ей, почему это плохая идея.   -  person ruakh    schedule 02.04.2015


Ответы (2)


SQL Server не имеет очень хороших функций для работы со строками. Это проще с подзапросами:

select firstname,
       stuff(reverse(stuff(reverse(legalname), 1, len(lastname) + 1, '')),
             1, len(firstname) + 1, '')
from (select legalname,
             left(legalname, charindex(' ', legalname) - 1) as firstname,
             right(legalname, charindex(' ', reverse(legalname)) - 1) as lastname
      . . .
     ) c

Однако я был бы очень осторожен, потому что не у всех людей имена из трех частей. А у других есть суффиксы (JR, SR) и другие усложнения.

person Gordon Linoff    schedule 01.04.2015
comment
Этот запрос не работает, он выдает ошибку: Msg 174, уровень 15, состояние 1, строка 2. Для обратной функции требуется 1 аргумент(ы). Сообщение 102, уровень 15, состояние 1, строка 9 Неверный синтаксис рядом с «c». - person Geetanjali Sachdeva; 01.04.2015
comment
замените ... на FROM <yourtablename>. - person ughai; 02.04.2015

Вы можете попробовать что-то вроде этого.

;WITH c AS 
(
    SELECT 'Marilyn Kean Kirkland' AS legalname
    UNION ALL SELECT 'J Smith' AS legalname
)
SELECT
    SUBSTRING(legalname,1,space1) firstname,
    SUBSTRING(legalname,space1,space2 - space1 + 1) middlename,
    SUBSTRING(legalname,space2 + 1,totallength - space2) lastname
FROM
(
    SELECT
        legalname,
        CHARINDEX(' ',legalname) space1,
        LEN(legalname) - CHARINDEX(' ',REVERSE(legalname)) space2,
        LEN(legalname) as totallength
    FROM c
)c
GO

Как отмечалось выше другими пользователями, эти сценарии будут работать с пользователями, которые имеют только 3 части или 2 части имени.

person ughai    schedule 02.04.2015