简体   繁体   English

将全名分为名字和姓氏

[英]Splitting a Full Name into First and Last Name

I have a list of customer whose name is given as a full name. 我有一个客户列表,其名称为全名。 I want to create a function that takes the full name as parameter and returns the first and last name separately. 我想创建一个将全名作为参数并分别返回名字和姓氏的函数。 If this is not possible I can have two separate functions one that returns the first name and the other that returns the last name. 如果不可能,我可以有两个单独的函数,一个返回名字,另一个返回姓氏。 The full name list contains names that have a maximum of three words. 全名列表包含最多三个单词的名称。 What I want is this:- 我想要的是:

  • When a full name is composed of two words. 全名由两个词组成时。 The first one should be the name and the second one should be the last name. 第一个应该是名称,第二个应该是姓氏。
  • When a full name is composed of three words. 全名由三个词组成时。 The first and middle words should be the first name while the third word should be the last name. 第一个单词和中间单词应该是名字,第三个单词应该是姓氏。

Example:- 例:-

**Full Name**    
John Paul White    
Peter Smith    
Ann Marie Brown    
Jack Black    
Sam Olaf Turner

Result:- 结果:-

**First Name    Last Name**    
John Paul     White    
Peter         Smith      
Ann Marie     Brown    
Jack          Black    
Sam Olaf      Turner

I have search and found solutions that are not working as intended and would like some advice. 我搜索并找到了无法按预期运行的解决方案,希望获得一些建议。

Keeping it short and simple 简短而简单

DECLARE @t TABLE(Fullname varchar(40))
INSERT @t VALUES('John Paul White'),('Peter Smith'),('Thomas')

SELECT
  LEFT(Fullname, LEN(Fullname) - CHARINDEX(' ', REVERSE(FullName))) FirstName,
  STUFF(RIGHT(FullName, CHARINDEX(' ', REVERSE(FullName))),1,1,'') LastName
FROM
  @t

Result: 结果:

FirstName  LastName
John Paul  White
Peter      Smith
Thomas     NULL

If you are certain that your names will only ever be two or three words, with single spaces, then we can rely on the base string functions to extract the first and last name components. 如果确定您的名字只会是两个或三个单词,且带有单个空格,那么我们可以依靠基本字符串函数来提取名字和姓氏成分。

SELECT
    CASE WHEN LEN(col) = LEN(REPLACE(col, ' ', '')) + 2
         THEN SUBSTRING(col, 1,
                        CHARINDEX(' ', col, CHARINDEX(' ', col) + 1) - 1)
         ELSE SUBSTRING(col, 1, CHARINDEX(' ', col) - 1)
    END AS first,
    CASE WHEN LEN(col) = LEN(REPLACE(col, ' ', '')) + 2
         THEN SUBSTRING(col,
                        CHARINDEX(' ', col, CHARINDEX(' ', col) + 1) + 1,
                        LEN(col) - CHARINDEX(' ', col, CHARINDEX(' ', col)))
         ELSE SUBSTRING(col,
                        CHARINDEX(' ', col) + 1,
                        LEN(col) - CHARINDEX(' ', col))
    END AS last
FROM yourTable;

Yuck, but it seems to work. 不错,但似乎可行。 My feeling is that you should fix your data model at some point. 我的感觉是您应该在某个时候修复数据模型。 A more ideal place to scrub your name data would be outside the database, eg in Java. 更理想的清理名称数据的地方是在数据库外部,例如在Java中。 Or, better yet, fix the source of your data such that you record proper first and last names from the very beginning. 或者,更好的是,修复数据源,以便从一开始就记录正确的名字和姓氏。

Demo here: 演示在这里:

Rextester 右旋酯

You're trying to do two things at once...I won't solve for you, but here's the direction I'd take: 您正在尝试同时做两件事...我不会为您解决,但是这是我的方向:

1) Check this out for string splitting: https://ole.michelsen.dk/blog/split-string-to-table-using-transact-sql.html . 1)进行字符串拆分检查: https : //ole.michelsen.dk/blog/split-string-to-table-using-transact-sql.html This will allow you to parse the name into a temp table and you can perform your logic on it to create names based on your rules 这将允许您将名称解析到临时表中,并且可以对其执行逻辑以根据规则创建名称

2) Create this as a table-valued function so that you can return a single row of parsed FirstName, LastName from your parameter. 2)将其创建为表值函数,以便您可以从参数中返回已解析的FirstName,LastName的单行。 That way you can join to it and include in your results 这样,您可以加入其中并纳入结果中

Have you tried by Using PARSENAME Function? 您是否尝试过使用PARSENAME函数?

The last method in splitting a full name into its corresponding first name and last name is the use of the PARSENAME string function, as can be seen from the following script: 将全名分为其相应的名字和姓氏的最后一种方法是使用PARSENAME字符串函数,如以下脚本所示:

    DECLARE @FullName VARCHAR(100)
    SET @FullName = 'John White Doe'

    SELECT CONCAT(PARSENAME(REPLACE(@FullName, ' ', '.'), 3),' ',PARSENAME(REPLACE(@FullName, ' ', '.'), 2)) AS [FirstName],
  PARSENAME(REPLACE(@FullName, ' ', '.'), 1) AS [LastName]

For more information, Goto this Site 有关更多信息,请转到此站点 在此处输入图片说明

This is the output.. 这是输出。

在此处输入图片说明

Make it a table-valued function. 使它成为表值函数。

see here for an example 请看这里的例子

And this is the code you need to create your function. 这是创建函数所需的代码。 Basically you just need to split your LastName 基本上,您只需要拆分您的姓氏

IF OBJECT_ID(N'dbo.ufnParseName', N'TF') IS NOT NULL
    DROP FUNCTION dbo.ufnParseName;
GO
CREATE FUNCTION dbo.ufnParseName(@FullName VARCHAR(300))
RETURNS @retParseName TABLE 
(
-- Columns returned by the function    
FirstName nvarchar(150) NULL,  
LastName nvarchar(50) NULL
)
AS 
-- Returns the spliced last name.
BEGIN

     DECLARE 
        @FirstName nvarchar(250),
        @LastName nvarchar(250);
    -- Get common contact information

    SELECT @LastName = RTRIM(RIGHT(@FullName, CHARINDEX(' ', REVERSE(@FullName)) - 1));
    SELECT @FirstName = LTRIM(RTRIM(Replace(@FullName, @LastName, '')))

     INSERT @retParseName
        SELECT @FirstName, @LastName;

    RETURN;
END

You can run as SELECT * FROM dbo.ufnParseName('MJ K'); 您可以作为SELECT * FROM dbo.ufnParseName('MJ K');

Why Table-Valued-Function 为什么要使用表值函数

You can get rid off the duplication of your sql query and achieve DRY 您可以摆脱重复的SQL查询并实现DRY

Another option (just for fun) is to use a little XML in concert with an CROSS APPLY 另一个选择(只是为了好玩)是与CROSS APPLY一起使用一些XML

Example

Select FirstName = ltrim(reverse(concat(Pos2,' ',Pos3,' ',Pos4,' ',Pos5)))
      ,LastName  = reverse(Pos1)
 From  YourTable A
 Cross Apply (
                Select Pos1 = xDim.value('/x[1]','varchar(max)')
                      ,Pos2 = xDim.value('/x[2]','varchar(max)')
                      ,Pos3 = xDim.value('/x[3]','varchar(max)')
                      ,Pos4 = xDim.value('/x[4]','varchar(max)')
                      ,Pos5 = xDim.value('/x[5]','varchar(max)')
                From  (Select Cast('<x>' + replace(reverse(A.[Full Name]),' ','</x><x>')+'</x>' as xml) as xDim) XMLData
             ) B

Returns 退货

FirstName               LastName
John Paul               White
Peter                   Smith
Ann Marie               Brown
Jack                    Black
Sam Olaf                Turner
                        Cher
Sally Anne Bella Donna  Baxter

You can try the below query. 您可以尝试以下查询。 It is written as per your requirement and it only handles full_name with 2 or 3 parts in it. 它是根据您的要求编写的,并且只处理其中包含2或3部分的full_name。

;WITH cte AS(
    SELECT full_name, (LEN(full_name) - LEN(REPLACE(full_name, ' ', '')) + 1) AS size FROM @temp
    )

SELECT FirstName = 
    CASE 
        WHEN size=3 THEN PARSENAME(REPLACE(full_name, ' ', '.'), 3) + ' ' + PARSENAME(REPLACE(full_name, ' ', '.'), 2)
        ELSE PARSENAME(REPLACE(full_name, ' ', '.'), 2)
    END,
    PARSENAME(REPLACE(full_name, ' ', '.'), 1) AS LastName
FROM cte

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM