从全名字段获取中间名

时间:2019-04-20 08:45:19

标签: sql sql-server

所以,我有一些函数来获取名字和姓氏,就像这样:

create function udf_get_first_name (@string nvarchar(100))
    returns nvarchar(50)
as
begin
    declare @first_name nvarchar(50)
        set @string = ltrim(@string)
        set @string = rtrim(@string)

    if dbo.udf_get_number_of_spaces(@string) > 0
        set @first_name = left(@string, charindex(' ',@string) -1)
    else
        set @first_name = @string
    return @first_name
end

create function udf_get_last_name (@string nvarchar(100))
returns nvarchar(50)
as
    begin 
        set @string = ltrim(@string)
        set @string = rtrim(@string)
        if dbo.udf_get_number_of_spaces (@string) > 0
            begin
                set @string = reverse(@string)
                set @string = left(@string, charindex(' ', @string) -1)
                set @string = reverse(@string)
            end
        return @string
    end



我需要能够获得中间名,并且不能将我的头一直缠绕到到目前为止搜索中所阅读的内容。不知道我是否只是愚蠢。

我还需要能够将格式为L / M / F的名称也排序到适当的列中,这给我带来了更大的麻烦。

编辑:并非所有记录都有中间名。

5 个答案:

答案 0 :(得分:3)

您可以使用以下解决方案,并使用函数以指定格式获取名称的一部分或全名:

--
-- function to get a part of a fullname or to reformat the fullname.
-- @fullname - the fullname to get the part from or to reformat.
-- @format - the format of the output using F (firstname), M (middlename) and L (lastname).
-- the function returns the fullname in specified format or NULL if input is not valid 
-- or the part of name is empty.
--
CREATE FUNCTION GetNamePart(@fullname VARCHAR(200), @format VARCHAR(30))
RETURNS VARCHAR(200)
AS
BEGIN

  -- replace multiple spaces of the fullname and trim the result.
  SET @fullname = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(@fullname, ' ', '<>'), '><', ''), '<>', ' ')))

  -- get the different name parts (firstname, middlename and lastname) of the fullname.
  DECLARE @first_name VARCHAR(100)
  SET @first_name = LTRIM(RTRIM(LEFT(@fullname, CHARINDEX(' ', @fullname))))
  DECLARE @last_name VARCHAR(100)
  SET @last_name = LTRIM(RTRIM(RIGHT(@fullname, CHARINDEX(' ', REVERSE(@fullname)))))
  DECLARE @middle_name VARCHAR(100)
  SET @middle_name = LTRIM(RTRIM(SUBSTRING(@fullname, LEN(@first_name) + 1, LEN(@fullname) - LEN(@first_name) - LEN(@last_name))))

  -- init the formatted name of the fullname.
  DECLARE @formatted_name VARCHAR(100)

  -- return only the formatted name if format string is valid.
  IF PATINDEX('%[^LMF]%', UPPER(@format)) > 0
    SET @formatted_name = ''
  ELSE
    BEGIN
      SET @format = REPLACE(REPLACE(REPLACE(@format, 'M', '##M##'), 'L', '##L##'), 'F', '##F##')
      SET @formatted_name = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(UPPER(@format), '##F##', @first_name + ' '), '##M##', @middle_name + ' '), '##L##', @last_name + ' ')))
    END

   -- check the input (@fullname) for valid value (firstname, lastname or firstname, middlename, lastname).
   IF PATINDEX('%_ %_% _%', @fullname) = 0 AND PATINDEX('%_ _%', @fullname) = 0
     SET @formatted_name = ''

   -- return the new formatted name and replace multiple spaces.
  RETURN NULLIF(REPLACE(REPLACE(REPLACE(@formatted_name, ' ', '<>'), '><', ''), '<>', ' '), '')
END

此功能GetNamePart使用两个参数(@fullname@format)。第一个参数@fullname是包含名字,姓氏和中间名的全名。第二个参数定义名称的输出格式。您可以使用字母F(姓),M(中间名)和L(姓)来定义输出格式。

因此,您可以使用函数GetNamePart来获取全名的中间名:

SELECT dbo.GetNamePart(fullname, 'M') FROM table_name

...或重新格式化全名:

SELECT dbo.GetNamePart(fullname, 'LMF') FROM table_name

demo on dbfiddle.uk (演示和测试用例)


但是您也可以使用SELECT查询来获取名称的各个部分,而无需使用函数:

SELECT
  LTRIM(RTRIM(LEFT(fullname, CHARINDEX(' ', fullname)))) AS first_name,
  LTRIM(RTRIM(RIGHT(fullname, CHARINDEX(' ', REVERSE(fullname))))) AS last_name,
  LTRIM(RTRIM(CASE WHEN PATINDEX('%_ %_% _%', fullname) > 0 THEN SUBSTRING(fullname, CHARINDEX(' ', fullname) + 1, (CHARINDEX(' ', fullname, CHARINDEX(' ', fullname)+1)-(CHARINDEX(' ', fullname) + 1))) ELSE '' END)) AS middle_name
FROM table_name

demo on dbfiddle.uk

答案 1 :(得分:1)

类似于Sebastian Brosch的答案。在看到他的回答后,我还添加了TRIM函数。在此查询中,没有必要。但这真是太好了。例如,如果用户错误地添加了多个空格,则将其删除。

可能会有更好或更简单的方法来获得名字,中间名和姓氏。但这是我目前想出的方式。

CREATE FUNCTION dbo.SplitFullName(
    @FullName NVARCHAR(MAX),
    @Format NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS 
BEGIN
    DECLARE @FN NVARCHAR(MAX);
    DECLARE @MN NVARCHAR(MAX);
    DECLARE @LN NVARCHAR(MAX); 
    DECLARE @RV NVARCHAR(MAX); 

    SET @FN = RTRIM(LTRIM(SUBSTRING(@FullName,0, CHARINDEX(' ',@FullName))));
    SET @MN = RTRIM(LTRIM(SUBSTRING(@FullName, CHARINDEX(' ',@FullName) + 1 , LEN(@FullName) - (CHARINDEX(' ',@FullName) + CHARINDEX(' ',REVERSE(@FullName)))+1)));
    SET @LN = RTRIM(LTRIM(REVERSE(SUBSTRING(REVERSE(@FullName),0, CHARINDEX(' ',REVERSE(@FullName))))));

    IF (@Format='FN') 
        SET @RV = CASE WHEN LEN(@FN) = 0 THEN NULL ELSE @FN END;
    ELSE IF (@Format='MN') 
        SET @RV = CASE WHEN LEN(@MN) = 0 THEN NULL ELSE @MN END;
    ELSE IF (@Format='LN') 
        SET @RV = CASE WHEN LEN(@LN) = 0 THEN NULL ELSE @LN END;;
    ELSE
        SET @RV = CONCAT(@LN, ' ',  CASE WHEN LEN(@MN) = 0 THEN NULL ELSE CONCAT(@MN , ' ') END, @FN);

    RETURN @RV;
END;

示例01

SELECT dbo.SplitFullName('Antonio P. Green', 'FN')  AS FN,
       dbo.SplitFullName('Antonio P. Green', 'MN')  AS MN,
       dbo.SplitFullName('Antonio P. Green', 'LN')  AS LN, 
       dbo.SplitFullName('Antonio P. Green', 'LMF') AS LMF;

+---------+----+-------+------------------+
|   FN    | MN |  LN   |       LMF        |
+---------+----+-------+------------------+
| Antonio | P. | Green | Green P. Antonio |
+---------+----+-------+------------------+

示例02

select dbo.SplitFullName('Cindy Bertha Collier Sproles', 'FN')  AS FN,
       dbo.SplitFullName('Cindy Bertha Collier Sproles', 'MN')  AS MN,
       dbo.SplitFullName('Cindy Bertha Collier Sproles', 'LN')  AS LN,
       dbo.SplitFullName('Cindy Bertha Collier Sproles', 'LMF') AS LMF;

+-------+----------------+---------+------------------------------+
|  FN   |       MN       |   LN    |             LMF              |
+-------+----------------+---------+------------------------------+
| Cindy | Bertha Collier | Sproles | Sproles Bertha Collier Cindy |
+-------+----------------+---------+------------------------------+

示例03

SELECT dbo.SplitFullName('Tristan Jackson', 'FN')  AS FN,
       dbo.SplitFullName('Tristan Jackson', 'MN')  AS MN,
       dbo.SplitFullName('Tristan Jackson', 'LN')  AS LN, 
       dbo.SplitFullName('Tristan Jackson', 'LMF') AS LMF;

+---------+------+---------+-----------------+
|   FN    |  MN  |   LN    |       LMF       |
+---------+------+---------+-----------------+
| Tristan | NULL | Jackson | Jackson Tristan |
+---------+------+---------+-----------------+

答案 2 :(得分:0)

您可以使用多个逗号分隔的CTE处理此问题。

declare @str nvarchar(max) ='kareena kapoor khan';

with 
t0 AS (select charindex(' ',@str) pos, @str name ),
t1 AS (select charindex(' ',@str,pos+1)pos,@str name from  t0)
select substring(t0.name,0,t0.pos) "firstName",
       substring(t0.name,t0.pos+1,(t1.pos-t0.pos)) "MiddleName",
       substring(t0.name,t1.pos+1,(len(t0.name)- t1.pos)) "Lastname" 
from    t0
inner join t1 on t0. name= t1.name

输出

|名字| MiddleName |姓氏

| kareena |卡普尔|汗

此外,您无需创建3个用于名字,中间名和姓氏的函数,而只需创建一个函数并将参数作为@namepart传递即可。

答案 3 :(得分:0)

未来从sql-server 2016开始: 使用STRING_SPLIT函数

Use Northwind
Go

SELECT ProductID, value  
FROM Products  
CROSS APPLY STRING_SPLIT(ProductName, ' ');  

通过该查询,您可以拆分名称...,然后通过Row()函数使用,可以选择中间名称。


STRING_SPLIT要求兼容性级别至少为130。如果该级别小于130,则SQL Server无法找到STRING_SPLIT函数。

答案 4 :(得分:-1)

选择Ltrim(SUBSTRING(name,CharIndex('',name),    当(CHARINDEX('',name,CHARINDEX(''',name)+1)-CHARINDEX('',name))<= 0时    else CHARINDEX('',name,CHARINDEX('',name)+1)-CHARINDEX('',name)end))作为MiddleName     来自TableName

相关问题