SQL修复名称列分隔大写字母

时间:2013-04-01 21:51:04

标签: sql case

我们有一个技术支持代理陷入困境,不小心在我们的“FullName”列中删除了第一个中间名和姓氏之间的空格。

所以而不是

John Alan Smith

名字读

JohnAlanSmith

我们在各个列中没有名称,也没有其他名称来源。这适用于第三方应用程序。

我们在数据库中有超过1500个用户,因此我们需要轻松纠正问题。我能想到的唯一方法是检测资本。当然,我们需要以某种方式排除名字中间的首都,如麦当劳等。

我们可以发出一条SQL语句吗?即使我们只需要手动更正100个名称,也会比1500 +更好。

3 个答案:

答案 0 :(得分:1)

我无法抗拒尝试这一点。以下代码适用于SQL Server,它实际上可以工作(您可以在sqlfiddle上查看)。

这是一个多步骤的过程。我们的想法是通过连接一堆数字并检查字符的值以确定它是否大写来识别名称中每个大写字母的位置。每个大写字母都在它自己的行上。

然后,为其提取名称部分,并将每个字符串的字符串连接在一起。这个方法有效,假设第一个字母大写(如果不是这样,很容易修复)。

另外,请记住一些首都不是“边缘”:“麦加维”,“陈史密斯”等等。

每个步骤都会因数据库而异。

with somenums as (
      select 1 as n union all select 2 union all select 3 union all select 4 union all select 5
     ),
     nums as (
      select ROW_NUMBER() over (order by (select NULL)) as n
      from somenums s cross join somenums s2
     ),
     test as (
         select 'JohnAlanSmith' as name union all
         select 'MaryElizabethChou'
     ),
     caps as (
      select name, n
      from test join
           nums
           on ascii(SUBSTRING(test.name, nums.n, 1)) between ascii('A') and ascii('Z')
    ),
    nameparts as (
     select name, n, nextn, SUBSTRING(name, n, coalesce(nextn - n, 1000)) as namepart
     from (select name, n,
                  (select min(n) from caps c2 where c2.name = c.name and c2.n > c.n
                  ) as nextn
           from caps c
          ) c
    )
select name,
       STUFF((select ' '+namepart
              from nameparts np2
              where np2.name = np.name
              order by n
              for xml path ('')
             ), 1, 1, ''
            ) as betterName
from nameparts np
group by name

答案 1 :(得分:0)

对于MySQL:

当你不想浪费太多时间编写一个复杂的函数时,你可能会尝试这样的事情:

/*test data*/
create table foo(name varchar(50));
insert into foo values ('JohnAndySmith');

select
name,
trim(replace(replace(name, 'A', ' A'), 'S', ' S'))
from
foo

直播here

当然,你必须为整个字母表做这件事。 TRIM()函数删除第一个字母前面的空格。

有关我使用的功能的更多信息,请参阅manual

答案 2 :(得分:0)

根据你的RDBMS,这样的东西可以工作。这是专门针对SQL Serer并使用一个接受字符串中字段和位置的函数,并将字符串返回到下一个大写字母:

select field, fname, mname, dbo.ReturnCapString(field,len(fname)+len(mname)+1) lname
from
  (
    select field, fname, dbo.ReturnCapString(field,len(fname)+1) mname
    from
      (
      select field, dbo.ReturnCapString(field,1) fname
      from yourtable
        ) t
    ) t2

函数 - 函数的主要内容是ASCII检查角色是否为大写:

CREATE FUNCTION ReturnCapString (@String VARCHAR(100), @Pos int) 
RETURNS varchar(100)
AS 
BEGIN 
   DECLARE @return varchar(100) 
   DECLARE @position INT 
   DECLARE @counter INT 

   SET @position = @Pos + 1
   SET @counter = 1
   SET @return = ''

   WHILE @position <= DATALENGTH(@string) AND @return = ''
   BEGIN 
       IF ASCII(SUBSTRING(@string, @position, 1)) BETWEEN 65 AND 90  
           SELECT @return = SUBSTRING(@string, @pos, @counter)

       SET @position = @position + 1 
       SET @counter = @counter + 1 

   END 

   IF @return = '' 
   BEGIN
     SET @return = SUBSTRING(@String, @Pos, LEN(@string))
   END 

   RETURN @return 
END

当然,SQL Fiddle来证明。

BTW - 感谢有趣的问题!虽然这并不完美(不要认为任何事情会100%完美)如果你需要潜在地标出任何明显的问题,请使用这个小提琴:http://sqlfiddle.com/#!3/77f446/10

FLAG   FIELD            FNAME    MNAME    LNAME
       JohnAlanSmith    John     Alan     Smith
       McDonalds        Mc                Donalds
X      JimBobMacDonald  Jim      Bob      Mac