将列拆分为各个列

时间:2014-09-29 15:47:59

标签: sql

-- 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. 将条目(Mrs,Mr,Miss等)视为标题,并忽略标题后的点

  2. 当我们有标题和单个名称时,将其作为标题,姓氏返回

  3. 当我们有标题和两个名称将其作为Title,FirstName和LastName

  4. 返回时
  5. 当我们有title和三个名字时,返回Title,FirstName并将其余部分视为LastName

  6. 如果我们没有标题,请将数据重新命名为FirstName,LastName

  7. 无需任何功能。

  8. 所以我们可以用这种形式获得价值:

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

    谢谢

2 个答案:

答案 0 :(得分: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

如果这可以帮助您解决问题,请接受它作为答案。 :)

答案 1 :(得分: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

非常感谢你的帮助

相关问题