2014-09-29 77 views
-4
-- Create table dbo.FullNameTest 
IF OBJECT_ID('FullNameTest') IS NOT NULL BEGIN 
    DROP TABLE dbo.FullNameTest; 
END; 

CREATE TABLE FullNameTest 
(
    ID   INT   Not Null IDENTITY 
    , FullName NVARCHAR(80) Not Null 
    , CONSTRAINT PK_ID PRIMARY KEY CLUSTERED(ID) 
); 
GO 

INSERT INTO FullNameTest 
VALUES('Mr Hog Finn Gad'), ('Grace Bruce'), ('Dr.Paul'), ('Master Clark James'), ('Mrs.Rignald') 

SELECT * FROM FullNameTest 

規則拆分一列到各列

  1. 款待條目(太太,先生,小姐等)作爲標題,而忽略標題

  2. 後點當我們有標題和一個名稱,將其作爲標題返回,姓氏

  3. 當我們有標題和兩個名稱將其作爲標題,名字和姓氏返回時

  4. 當我們有標題和三個名字,回到標題,名字和治療,其餘爲姓氏

  5. 當我們有沒有標題,reurn數據作爲名字,姓氏

  6. 沒有所需的功能。

因此,我們可以以這種形式獲得的值:

Title FirstName LastName 
------------------------------ 
Mr  Hog   Finn Gad 
Null Grace  Bruce 
Dr  Null  Paul 
Master Clark  James 
Mrs  Null  Rignald 

謝謝

+1

根據你的榜樣,你不僅要拆分標題,首先姓,名稱,你也想清理你的數據。我會建議分開處理它們。顯然,分離「John Smith先生」的相同方法對於「MsCollins」不起作用。 – rwking 2014-09-29 15:56:31

回答

0

編輯:***要測試結果自己,使用以下方法來創建你的全名錶,然後運行代碼以創建標題表,然後運行下面的解決方案代碼。結果正是你所要求的。

CREATE TABLE #FullNameTest 
(
    ID   INT   Not Null IDENTITY 
    , FullName NVARCHAR(80) Not Null 
); 
GO 

INSERT INTO #FullNameTest 
VALUES('Mr Hog Finn Gad'), ('Grace Bruce'), ('Dr.Paul'), ('Master Clark James'), ('Mrs.Rignald') 

這可能不適用於任何情況,它需要使用具有標題的參考表,但它應該讓您開始。同樣,我會建議加入一些數據驗證約束,以免意外輸入。如果這不可行,那麼先運行一些算法來清理數據。當你嘗試在SQL中做這樣的事情時,它會變得雜亂無章。

創建一個帶標題和標題長度的標題參考表。

create table #title (Title varchar(15), Long as len(Title)) 

insert into #title (Title) values 
('Mr'), 
('Mister'), 
('Ms'), 
('Miss'), 
('Mrs'), 
('Misses'), 
('Dr'), 
('Doctor'), 
('Senator'), 
('Officer'), 
('Master') 

你的表是這樣的:

Mr  2 
Mister 6 
Ms  2 
Miss 4 
Mrs  3 
Misses 6 
Dr  2 
Doctor 6 
Senator 7 
Officer 7 
Master 6 

那麼你已經有了這個代碼塊滔天試圖計入輸入的每一個情況下,你可能有。再次嘗試 - 如果可能,請嘗試先清理數據。否則,每當遇到意想不到的情況時,您都必須修改此代碼。

select y.RawName 
     , y.Title 
     , y.FName 
     , case when RawName like '%'+y.Title+'% %'+y.FName+'%' then RIGHT(RawName, len(RawName)-LEN(y.Title+'% %'+y.FName+' ')+1) 
       when Title is not null then RIGHT(RawName, len(RawName)-len(title)) 
       when Title is null and RawName like '% %' then RIGHT(RawName, len(RawName)-len(Fname)-1) 
      end LName 
from (  
     select RawName 
      , Title 
      , case when right(RawName, len(RawName)-len(title)-1) like '% %' 
         then left(right(RawName, len(RawName)-len(title)-1), CHARINDEX(' ', right(RawName, len(RawName)-len(title)-1),1)) 
        when RawName like '% %' 
         then left(RawName, CHARINDEX(' ', RawName, 1)) 
       end FName 
     from ( 
       select 
         replace(f.FullName, '.', '') RawName 
        , t.title Title 
        , ROW_NUMBER() over(partition by f.fullname order by len(t.title) desc) row_n 
       from #FullNameTest f 
        left join #title t 
         on left(f.fullname, t.long) = t.title 
       ) x 
     where row_n = 1 
    ) y 

根據您的樣品從上面,你只剩下以下幾點:

RawName    Title  FName LName 
DrPaul    Dr  NULL  Paul 
Grace Bruce   NULL  Grace Bruce 
Master Clark James Master Clark James 
Mr Hog Finn Gad  Mr  Hog  Finn Gad 
MrsRignald   Mrs  NULL  Rignald 

如果這是幫助你解決問題,請接受它作爲回答。 :)

+0

這並沒有產生正確的結果,而且性能也不盡如人意。謝謝 – dLight 2014-09-30 08:55:32

+0

呃,它產生了你在你的例子中所要求的。再試一次。如果你沒有得到正確的結果,那麼你在代碼中犯了一個錯誤。 – rwking 2014-09-30 13:31:23

+0

我確實給了你必須修改其他情況的免責聲明。它只會用於你提供的內容,你需要添加你自己的case語句來處理其他類型的輸入。 – rwking 2014-09-30 13:37:02

0

下面是我最終使用的代碼:

SELECT Title, 
     CASE 
     WHEN CHARINDEX(' ',PARTNAME) = 0 THEN NULL 
     ELSE LEFT(PARTNAME, CHARINDEX(' ',PARTNAME)) 
     END AS [FirstName], 
     CASE WHEN CHARINDEX(' ',PARTNAME) = 0 THEN PARTNAME 
     ELSE RIGHT(PARTNAME, LEN(PARTNAME) - CHARINDEX(' ', PARTNAME)) 
     END AS [LastName] 
FROM 
(
SELECT TITLE, LTRIM(REPLACE(REPLACE(FULLNAME,ISNULL(TITLE,''),''),'.','')) AS PARTNAME 
FROM (
SELECT CASE 
     WHEN CHARINDEX('DR ',FullName) = 1 THEN 'Dr' 
     WHEN CHARINDEX('DR.',FullName) = 1 THEN 'Dr' 
     WHEN CHARINDEX('MR ',FullName) = 1 THEN 'Mr' 
     WHEN CHARINDEX('MR.',FullName) = 1 THEN 'Mr' 
     WHEN CHARINDEX('MRS ',FullName) = 1 THEN 'Mrs' 
     WHEN CHARINDEX('MRS.',FullName) = 1 THEN 'Mrs' 
     WHEN CHARINDEX('MISS ',FullName) = 1 THEN 'Miss' 
     WHEN CHARINDEX('MISS.',FullName) = 1 THEN 'Miss' 
     WHEN CHARINDEX('MASTER ',FullName) = 1 THEN 'Master' 
     WHEN CHARINDEX('MASTER.',FullName) = 1 THEN 'Master' 
    ELSE NULL 
    END AS [Title], FullName 
FROM FullNameTest 
) B 
) C 

非常感謝您的幫助

+0

使用你的代碼,像'JohnPaul'這樣的名字給出一個空值。使用我的,至少你在LastName中得到了一些東西。 – rwking 2014-09-30 13:46:05