我们有一个技术支持代理陷入困境,不小心在我们的“FullName”列中删除了第一个中间名和姓氏之间的空格。
所以而不是
John Alan Smith
名字读
JohnAlanSmith
我们在各个列中没有名称,也没有其他名称来源。这适用于第三方应用程序。
我们在数据库中有超过1500个用户,因此我们需要轻松纠正问题。我能想到的唯一方法是检测资本。当然,我们需要以某种方式排除名字中间的首都,如麦当劳等。
我们可以发出一条SQL语句吗?即使我们只需要手动更正100个名称,也会比1500 +更好。
答案 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/10FLAG FIELD FNAME MNAME LNAME
JohnAlanSmith John Alan Smith
McDonalds Mc Donalds
X JimBobMacDonald Jim Bob Mac