所以这是一个尝试,但正如我所说,我认为您不会在本机 T-SQL 中获得快速解决方案。
首先,如果您还没有数字表,请创建一个:
SET NOCOUNT ON;
DECLARE @UpperLimit int = 4000;
;WITH n AS
(
SELECT rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
)
SELECT [Number] = rn - 1
INTO dbo.Numbers FROM n
WHERE rn <= @UpperLimit + 1;
CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers([Number]);
然后创建两个函数。一个将字符串拆分成一个表,然后另一个重新加入第一个函数的结果但忽略任何后续重复项。
CREATE FUNCTION dbo.SplitStrings
(
@List nvarchar(4000),
@Delim char(1)
)
RETURNS TABLE
AS
RETURN ( SELECT
rn = ROW_NUMBER() OVER (ORDER BY CHARINDEX(@Delim, @List + @Delim)),
[Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
FROM dbo.Numbers
WHERE Number <= LEN(@List)
AND SUBSTRING(@Delim + @List, [Number], 1) = @Delim
);
GO
第二个功能:
CREATE FUNCTION dbo.RebuildString
(
@List nvarchar(4000),
@Delim char(1)
)
RETURNS nvarchar(4000)
AS
BEGIN
RETURN ( SELECT newval = STUFF((
SELECT @Delim + x.[Value] FROM dbo.SplitStrings(@List, @Delim) AS x
LEFT OUTER JOIN dbo.SplitStrings(@List, @Delim) AS x2
ON x.rn = x2.rn + 1
WHERE (x2.rn IS NULL OR x.value <> x2.value)
ORDER BY x.rn
FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
);
END
GO
现在您可以针对您在问题中提供的两个示例进行尝试:
;WITH cte(colname) AS
(
SELECT 'Jhon\Jhon\Jane\Mary\Bob'
UNION ALL SELECT 'Mary\Jane\Mary\Bob'
)
SELECT dbo.RebuildString(colname, '\')
FROM cte;
结果:
Jhon\Jane\Mary\Bob
Mary\Jane\Mary\Bob
但我强烈、强烈、强烈建议您在决定使用它之前根据您的典型数据大小彻底测试它。