【发布时间】:2011-02-01 16:45:05
【问题描述】:
我怎样才能让 SQL 进行刺痛并返回传递给它的每个单词的第一个字母。
我想使用这个 UDF 为我在数据库中的人名生成首字母。
名称可以是 2 (fname, lname) 或 3(...mname) 字
我正在使用 sql2005
【问题讨论】:
标签: sql-server-2005 user-defined-functions
我怎样才能让 SQL 进行刺痛并返回传递给它的每个单词的第一个字母。
我想使用这个 UDF 为我在数据库中的人名生成首字母。
名称可以是 2 (fname, lname) 或 3(...mname) 字
我正在使用 sql2005
【问题讨论】:
标签: sql-server-2005 user-defined-functions
这应该适用于“Firstname Lastname”和“Firstname Middlename Lastname”组合。
DECLARE @name AS NVARCHAR(50)
SET @name = 'Firstname Middle Lastname'
SELECT SUBSTRING(@name, 1, 1) + --First initial
SUBSTRING(@name, CHARINDEX(' ', @name) + 1, 1) + --Middle/Last initial
CASE WHEN 0 <> CHARINDEX(' ', @name, CHARINDEX(' ', @name) + 1) -- More than two words
THEN SUBSTRING(@name, CHARINDEX(' ', @name, CHARINDEX(' ', @name) + 1) + 1, 1) --Last initial
ELSE '' --Have to add empty string to avoid NULLing entire result
END
当然,如果用户出于某种原因在他们的姓名之一中 有一个空格,则解析它时会遇到问题,但我怀疑在不将您的姓名存储在单独的字段。
【讨论】:
CREATE FUNCTION dbo.GetFirstLetter ( @Array VARCHAR(1000), @separator VARCHAR(10))
RETURNS @resultTable TABLE
(parseValue VARCHAR(100))
AS
BEGIN
DECLARE @separator_position INT
DECLARE @array_value VARCHAR(1000)
SET @array = @array + @separator
WHILE patindex('%' + @separator + '%' , @array) <> 0
BEGIN
SELECT @separator_position = patindex('%' + @separator + '%', @array)
SELECT @array_value = left(@array, @separator_position - 1)
INSERT @resultTable
VALUES (SUBSTRING(Cast(@array_value AS varchar), 1, 1))
SELECT @array = stuff(@array, 1, @separator_position, '')
END
RETURN
END
【讨论】:
对于 SQL Server 2017 及更高版本:
CREATE FUNCTION dbo.fnGetFirstChars (@string NVARCHAR(max), @seperator NVARCHAR(MAX))
RETURNS NVARCHAR(max)
AS BEGIN
DECLARE @result NVARCHAR(MAX)
SELECT @result = STRING_AGG(SUBSTRING(value, 1, 1), '')
FROM STRING_SPLIT(@string, @seperator)
RETURN @result
END;
【讨论】:
这是我的解决方案,它具有以下特点/特点:
我知道 OP 已指定在他的案例中只能有 2 或 3 个名称。我不介意。我只是分享一个可行的解决方案,如果它不是最适合特定问题的,那也没关系。
所以,函数如下:
CREATE FUNCTION dbo.fnGetInitials (@name varchar(max))
RETURNS varchar(max)
AS BEGIN
DECLARE @cutpos int, @spacepos int, @result varchar(max);
DECLARE @cutlist TABLE (CutPos int, SpacePos int);
SET @result = LTRIM(RTRIM(@name));
SET @cutpos = 2;
SET @spacepos = CHARINDEX(' ', @result);
WHILE @spacepos > 0 BEGIN
INSERT INTO @cutlist VALUES (@cutpos, @spacepos);
SET @spacepos = @spacepos + 1;
SET @cutpos = @spacepos + 1;
SET @spacepos = CHARINDEX(' ', @result, @spacepos);
END;
DELETE FROM @cutlist WHERE CutPos >= SpacePos;
SELECT @result = STUFF(@result, CutPos, SpacePos - CutPos, '')
FROM @cutlist
ORDER BY CutPos DESC;
RETURN @result;
END;
这是一个测试调用:
SELECT dbo.fnGetInitials(' John Ronald Reuel Tolkien ');
结果:
----------------------------------------------------------------------------------------------------
J R R Tolkien
【讨论】:
你也可以通过 xquery 来实现。
Declare @Xml XML
Declare @String Varchar(Max)
Declare @firstletter Varchar(Max)
Declare @delimiter Varchar(5)
SET @delimiter=' '
SET @String= 'THIS IS SQL'
SET @Xml = cast(('<a>'+replace(@String,@delimiter,'</a><a>')+'</a>') AS XML)
;WITH CTE AS
(SELECT A.value('.', 'varchar(max)') as [Column]FROM @Xml.nodes('a') AS FN(a) )
SELECT Stuff((SELECT '' + LEFT([Column],1)from CTE
FOR XML PATH ('') ),1,0,'')
这是完整的解决方案。
http://raresql.com/2013/04/12/sql-server-get-the-first-letter-of-each-word-in-a-string-column/
【讨论】:
图片比描述好 100 倍。下面是一个UDF声明的例子:
CREATE FUNCTION dbo.GetOnlyFirstLetters(@str NVARCHAR(4000),@sep NVARCHAR(10) )
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE @textXML XML
SELECT @textXML = CAST('<d>' + replace(@str, @sep, '</d><d>') + '</d>' AS XML)
DECLARE @result VARCHAR(8000)
SET @result = ''
SELECT @result = @result + LEFT(T.split.value ('.', 'nvarchar(max)'), 1)
FROM @textXML.nodes ('/d') T (split)
RETURN @result
END
GO
调用方法如下:
SELECT dbo.GetOnlyFirstLetters('Humayoun Kabir Sohel',' ');
结果将是:
HKS
【讨论】: