2016-11-15 91 views
-1

对于如 我有表如何分割全称到名字,中间名,姓氏和后缀在TSQL

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  | 
+0

[TSQL声明,以名称后缀(JR,锶,IV等)移动到另一字段(的可能的复制http://stackoverflow.com/questions/3711944/tsql-statement-to-move-名称后缀-rr-iv-etc-into-another-field) – Aron

+11

这是一个不平凡的问题,特别是因为生活在英语国家的许多文化都有文化命名系统,甚至没有“中间名称”。例如,玛丽亚·德洛斯·戈麦斯·德拉克鲁兹,玛丽·保罗·怀特(玛丽·保罗·怀特)(她的中间名是保罗,还是她有双重姓氏?)。没有简单的方法来正确地做你想要的名字,通常遇到的名字,因为歧义,你不能没有更多的信息解决。 – hatchet

+1

对这个问题的任何答案都将基于假设,主要是你的名字永远是FML,有或没有后缀。 @hatchet提到了太多的可能性。对此,有几十个类似的问题。所有对这些问题的回答只有在永远不变,定义的变量限制下才是正确的。所以,如果你的数据包含了你所显示的更多变体,你将会有很多CASE语句,并且/或者将不得不与其他人一起来回处理,直到处理完所有异常。如果你敢开始寻找空白空间 – scsimon

回答

0
SELECT 

d.First_Name 


,CASE WHEN 0 = CHARINDEX(' ',d.REST_OF_NAME) 
     THEN NULL 
     ELSE SUBSTRING(             ---- finds the middle name from rest of the name 
         d.REST_OF_NAME 
         ,1 
         ,CHARINDEX(' ',d.REST_OF_NAME)-1 
        ) 
     END AS Middle_Name 

,SUBSTRING(
      d.REST_OF_NAME            ---- finds the Last name from rest of the name 
      ,1 + CHARINDEX(' ', d.REST_OF_NAME) 
      ,LEN(d.REST_OF_NAME) 
      ) AS Last_Name 

,d.Suffix 
,d.CUSTOMER_NUMBER 
,D.Orignal_Data_String 
from 
(SELECT c.Suffix, 

CASE WHEN 0 = CHARINDEX(' ',c.Remainding_Name_Part) 
     THEN c.Remainding_Name_Part 
     ELSE SUBSTRING(             ---- substring first name fro rest of the name from reminding part of the name 
         c.Remainding_Name_Part 
         ,1 
         ,CHARINDEX(' ',c.Remainding_Name_Part)-1 
         ) 
    END AS First_Name 
,CASE WHEN 0 = CHARINDEX(' ',c.Remainding_Name_Part) 
     THEN NULL 
     ELSE SUBSTRING(
         c.Remainding_Name_Part 
         ,CHARINDEX(' ',c.Remainding_Name_Part)+1   ------ substring rest of the name after substracting firstname from the remainding partof the name 
         ,LEN(c.Remainding_Name_Part) 
         ) 
    END AS REST_OF_NAME 

,c.CUSTOMER_NUMBER 
,C.Orignal_Data_String 
FROM 
(SELECT 
CASE WHEN RIGHT(b.Name,2) IN ('IV','Jr','Sr') 
    THEN LTRIM(RTRIM(RIGHT(b.Name,2)))          ----finds suffix in name   
     WHEN RIGHT(b.Name,3) IN ('III','Esq',' II') 
     THEN LTRIM(RTRIM(RIGHT(b.Name,3))) 

ELSE NULL 
END AS [Suffix] 
, 
CASE WHEN RIGHT(b.Name,2) IN ('IV','Jr','Sr') 
    THEN LTRIM(RTRIM(LEFT(b.name,LEN(b.name)-2)))       ----finds remider part of name after subtrecting suffix   
     WHEN RIGHT(b.Name,3) IN ('III',' Esq',' II') 
     THEN LTRIM(RTRIM(LEFT(b.name,LEN(b.name)-3))) 

ELSE LTRIM(RTRIM(b.name)) 
END AS [Remainding_Name_Part] 
,B.CUSTOMER_NUMBER 
,B.Orignal_Data_String 


FROM 

(SELECT 
REPLACE(REPLACE(LTRIM(RTRIM(a.NAME)),' ',' '),' ',' ') AS [Name]   ------ Clears spaces 
,A.NAME AS [Orignal_Data_String] 
,a.CUSTOMER_NUMBER 
FROM 
(
SELECT NAME,CUSTOMER_NUMBER             ------ finds the customers 
FROM [FIS_CORE_FEEDS_DM].[dbo].[FIS_DAILY_CUST_TABLE] 
WHERE CUSTOMER_TYPE !='O' 
     )A 
    )B 
    )C 
)D 
0

正如其他人所评论的那样,这个问题太模糊(并且问题描述太复杂),无法提供特别有用的答案,但我仍会尝试。

我们可以提出一个解决方案,如果我们做一些假设这个名字值你想分裂:

  • 每个名称中包含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 

这还不是最完美的解决方案,但它说明的用法CHARINDEXSUBSTRING可以应用来分解像这样的字符串。这个查询肯定有一些冗余,可以用这个查询来实现,而且更优雅的方法来实现它(再加上它可能不适合你的数据集,因为上面的假设),但是希望这对你有帮助的出发点。

更简洁的解决方案可能是创建一个函数,该函数需要2个参数 - 一个字符串和一个整数,用于指示您希望从该字符串返回哪个“字”。然后,您可以从类似的CASE逻辑中调用此函数,以根据需要返回名称中的第一个,第二个,第三个或第四个单词。

如果您需要能够处理[First Name] [Middle Name] [Last Name]表单中的3个单词的名称(如我怀疑的那样),您可能需要构建可能的后缀列表并使用该列表来确定每个3个单词名称相应地有后缀或中间名。

相关问题