2016-11-15 66 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個單詞名稱相應地有後綴或中間名。