Как разделить полное имя на имя, отчество, фамилию и суффикс в TSQL

Например, у меня есть столбец FullName в таблице

FullName 
------------------
Smith Johns Sr
James Macoy
Krushit J Patel II
Sheldon Devid
Jeff vandorf Jr
Steve Smith I

И я хочу, чтобы результат понравился

|FirstName | Middle Name | lastName | Suffix |
|--------------------------------------------|
|Smith     | NULL        | Johns    | Null   |
|James     | NULL        | Macoy    | Null   |
|Krushit   | J           | Patel    | II     |
|Sheldon   | NULL        | Devid    | Null   |
|Jeff      | Null        | vandorf  |Jr      |
|Steve     |Smith        | Ronder   |I       |

person Krushit    schedule 15.11.2016    source источник
comment
Возможный дубликат инструкции TSQL   -  person Aron    schedule 16.11.2016
comment
Это нетривиальная проблема, особенно потому, что многие культуры, живущие в англоязычных странах, имеют культурные системы именования, в которых нет даже понятия отчества. Возьмем, к примеру, такое имя, как Мария де лос Анхелес Гомес де ла Крус или Мэри Пол Уайт (ее второе имя Пол или у нее двойная фамилия?). Нет простого способа правильно делать то, что вы хотите, с именами, которые обычно встречаются, из-за двусмысленностей, которые вы не можете разрешить без дополнительной информации.   -  person hatchet - done with SOverflow    schedule 16.11.2016
comment
Любой ответ на этот вопрос будет основан на предположениях, в первую очередь ваши имена всегда FML с суффиксом или без него. Как упомянул @hatchet, существует слишком много возможностей для рассмотрения. На SO есть десятки подобных вопросов. Все ответы на эти вопросы верны только при неизменном, определенном ограничении переменных. Итак, если ваши данные содержат больше вариаций, чем то, что вы показали, у вас будет много операторов CASE и/или вам придется идти вперед и назад с кем-то, пока не будут обработаны все исключения. Начните с поиска пробелов, если осмелитесь   -  person scsimon    schedule 16.11.2016


Ответы (1)


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

Мы можем предложить решение, если сделаем некоторые предположения о значениях имен, которые вы хотите разделить:

  • Каждое имя содержит от 2 до 4 «слов», разделенных одним пробелом.
  • Образуются 2 названия слов: [First Name] [Last Name]
  • Образуются 3 названия слов: [First Name] [Last Name] [Suffix]
  • Образуются 4 названия слов: [First Name] [Middle Name] [Last Name] [Suffix]

В этом случае мы могли бы решить следующим образом (если наши имена существуют в таблице с именем names с одним столбцом с именем Name):

SELECT      
 SUBSTRING(Name, 1, CHARINDEX(' ', Name) - 1) AS FirstName
,CASE LEN(Name) - LEN(REPLACE(Name, ' ', '')) + 1
    WHEN 2 THEN NULL
    WHEN 3 THEN NULL
    WHEN 4 THEN SUBSTRING(RIGHT(Name, LEN(Name) - CHARINDEX(' ', Name)), 1, CHARINDEX(' ', RIGHT(Name, LEN(Name) - CHARINDEX(' ', Name))) - 1)
 END AS [Middle Name]
,CASE LEN(Name) - LEN(REPLACE(Name, ' ', '')) + 1
    WHEN 2 THEN RIGHT(Name, LEN(Name) - CHARINDEX(' ', Name))
    WHEN 3 THEN SUBSTRING(RIGHT(Name, LEN(Name) - CHARINDEX(' ', Name)), 1, CHARINDEX(' ', RIGHT(Name, LEN(Name) - CHARINDEX(' ', Name))) - 1)
    WHEN 4 THEN SUBSTRING(RIGHT(Name, LEN(Name) - CHARINDEX(' ', Name, CHARINDEX(' ', Name) + 1)), 1, CHARINDEX(' ', RIGHT(Name, LEN(Name) - CHARINDEX(' ', Name, CHARINDEX(' ', Name) + 1))) - 1)
 END AS lastName
,CASE LEN(Name) - LEN(REPLACE(Name, ' ', '')) + 1
    WHEN 2 THEN NULL
    WHEN 3 THEN REVERSE(SUBSTRING(REVERSE(Name), 1, CHARINDEX(' ', REVERSE(Name)) - 1))
    WHEN 4 THEN REVERSE(SUBSTRING(REVERSE(Name), 1, CHARINDEX(' ', REVERSE(Name)) - 1))
 END AS Suffix
FROM names

Это не самое элегантное решение, но оно иллюстрирует использование CHARINDEX и SUBSTRING, которые можно применить для разбиения такой строки. Определенно существует некоторая избыточность, которую можно было бы устранить из этого запроса и более элегантных способов его реализации (плюс он может не подходить для вашего набора данных из-за приведенных выше предположений), но, надеюсь, это полезная отправная точка для вас.

Более изящным решением может быть создание функции, которая принимает 2 параметра — строку и целое число, чтобы указать, какое «слово» вы хотите вернуть из этой строки. Затем вы можете вызвать эту функцию из аналогичной CASE логики, чтобы вернуть первое, второе, третье или четвертое слово в имени по мере необходимости.

Если вам нужно иметь возможность обрабатывать имена из трех слов в форме [First Name] [Middle Name] [Last Name] (как я подозреваю, вы это делаете), вы, вероятно, захотите создать список возможных суффиксов и использовать этот список, чтобы определить, имеет ли каждое имя из трех слов суффикс. или отчество соответственно.

person 3N1GM4    schedule 16.11.2016