将泰国名字解析为第一个最后一个
Posted
技术标签:
【中文标题】将泰国名字解析为第一个最后一个【英文标题】:Parse Thai Name into First Last 【发布时间】:2019-01-17 14:42:20 【问题描述】:我需要将全名列表解析为名字和姓氏。如果包含中间名,则应将其包含在第一个名称字段中。
约翰·史密斯将是:
名字 = 约翰
姓氏 = 史密斯
约翰·J·史密斯将是:
名字 = John J.
姓氏 = 史密斯
问题是名称可能是泰语或英语字符集。我需要正确解析任何一组。我几乎什么都试过了……
DECLARE @FullName NVARCHAR(MAX) = N'กล้วยไม้ สวามิวัศดุ์'
--DECLARE @FullName NVARCHAR(MAX) = N'Mark C. Wilson'
SELECT
LEN(@FullName) AS StringLength,
LEN(@FullName) - LEN(REPLACE(@FullName,N' ', N'')),
LEN(REPLACE(@FullName,N' ', N'')),
@FullName AS FullName,
REVERSE(@FullName) AS ReverseName, -- This is obviously no Reverse of the string
CHARINDEX(N' ', REVERSE(@FullName)) AS LastSpaceLocation,
CHARINDEX(N' ', @FullName) AS FirstSpaceLocation,
LEN(@FullName) AS LenString,
STUFF(@FullName, 1, CHARINDEX(N' ', @FullName), N'') as FirstName,
RIGHT(@FullName, LEN(@FullName) - CHARINDEX(N' ', @FullName) + 1) as LastName,
LEFT(@FullName, LEN(@FullName) - CHARINDEX(N' ', REVERSE(@FullName))) AS FirstName,
STUFF(RIGHT(@FullName, CHARINDEX(N' ', REVERSE(@FullName))),1,1,N'') AS LastName,
LEN(@FullName),
REVERSE(@FullName),
REVERSE(' '),
LEN(@FullName) - CHARINDEX(reverse(' '), REVERSE(@FullName)) - LEN(' ') + 1
REVERSE
在使用泰语字符集时根本不起作用。
【问题讨论】:
发生这种情况是因为颠倒泰语名称会破坏组合字符,这些字符会“附加”到空格上,导致简单的字典搜索失败。在某种程度上,您可以通过强制二进制排序规则 (SELECT CHARINDEX(N' ', REVERSE(N'กล้วยไม้ สวามิวัศดุ์') COLLATE Latin1_General_BIN2)
) 来“解决”这个问题,但您很可能会遇到其他奇怪的问题。一旦你开始扩展到更多的语言(比如日语,或其他名称成分的顺序与英语不同的语言,或者根本没有姓氏),它只会变得更难。考虑尽可能不留下姓名。
您似乎有already asked 这个问题,现有的答案表明您基于反转字符串的方法存在根本缺陷,应该进行修改。很明显,自提出原始问题以来,您已经改进了查询,但问题保持不变;所以你可能需要编辑原来的 Q 而不是问一个新的。 VTC/重复。
SQL Server Parsing Thai Language Full Name to First Last的可能重复
我看到了这个,它不是我的问题的有效解决方案。 Reverse() 无法正常使用字符集。
【参考方案1】:
我不懂泰语(我没那么聪明),但也许这会有所帮助。
这里我们使用CROSS APPLY来“修复”字符串,然后是PasrName()
和Concat()
的小事
我应该补充一点,解析名称是一个滑坡。需要考虑
多字姓氏,即 De la Cruz 后缀即。理查德 R 卡佩莱蒂医学博士示例
Declare @YourTable table (FullName nvarchar(100))
Insert Into @YourTable values
('John Smith')
,('John J. Smith')
,(N'กล้วยไม้ สวามิวัศดุ์')
Select A.*
,LastName = replace(parsename(S,1),'|','.')
,FirstName = replace(concat(parsename(S,4),' '+parsename(S,3),' '+parsename(S,2)),'|','.')
From @YourTable A
Cross Apply ( values (replace(replace(FullName,'.','|'),' ','.'))) B(S)
退货
FullName LastName FirstName
John Smith Smith John
John J. Smith Smith John J.
กล้วยไม้ สวามิวัศดุ์ สวามิวัศดุ์ กล้วยไม้
EDIT 2008 版
Select A.*
,LastName = replace(parsename(S,1),'|','.')
,FirstName = replace( IsNull(parsename(S,4),'') + IsNull(' '+parsename(S,3),'') + IsNull(' '+parsename(S,2),''),'|','.')
From @YourTable A
Cross Apply ( values (replace(replace(FullName,'.','|'),' ','.'))) B(S)
【讨论】:
我很抱歉,但不幸的是,这是在 SS 2008 数据库中。我意识到这已经接近尾声,但是......无论如何,concat 是在 SQL Server 2012 中引入的。 @Mark:幸运的是,CONCAT
在这种情况下只是为了方便处理NULL
s。用+
连接字符串并用ISNULL(..., '')
包装连接的表达式可以降级。
@Mark Seed EDIT 2008 版
@Mark 只是说... 2008 年的扩展支持将于 2019 年 7 月结束。请将您的问题标记为 2008 年以避免假设。【参考方案2】:
我是泰国人,我知道的一件事是泰国人不使用中间名。
【讨论】:
有趣的事实......没有中间名的事情 我是荷兰人,我有两个。我从不提及它们,因为我不希望任何代码都能正确处理,尤其是数据库代码。 :-)以上是关于将泰国名字解析为第一个最后一个的主要内容,如果未能解决你的问题,请参考以下文章