如何限制 CTE 中的 STUFF 函数以删除重复单词前的字符
How to limit STUFF function within CTE for removing character before recurring word
的跟进问题
以下代码归功于@Larnu,如果重复单词“[BACKSPACE]”之前不再有字符,如何修改此代码以不生成空值。我相信空值的出现是因为 CHARINDEX()
函数在重复出现的 [BACKSPACE] 单词之前不再有字符时产生负值。该解决方案需要与 SQL Server 2008 兼容。
最终目标是凡是有[BACKSPACE]的地方,如果[BACKSPACE]前面有字符,就去掉;否则,不要尝试删除之前的字符。
DECLARE @inputString NVARCHAR(MAX);
SET @inputString = 'Word[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]sgred[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]SecondWord';
WITH rCTE AS(
SELECT V.YourColumn,
STUFF(V.YourColumn,CHARINDEX('[BACKSPACE]',V.YourColumn)-1,LEN('[BACKSPACE]')+1,'') AS ReplacedColumn,
1 AS Iteration
FROM (VALUES(@inputString))V(YourColumn)
UNION ALL
SELECT r.YourColumn,
STUFF(r.ReplacedColumn,CHARINDEX('[BACKSPACE]',r.ReplacedColumn)-1,LEN('[BACKSPACE]')+1,''),
r.Iteration + 1
FROM rCTE r
WHERE CHARINDEX('[BACKSPACE]',r.ReplacedColumn) > 0)
SELECT TOP (1) WITH TIES
r.YourColumn,
r.ReplacedColumn
FROM rCTE r
ORDER BY ROW_NUMBER() OVER (PARTITION BY r.YourColumn ORDER BY r.Iteration DESC);
期望的输出是'SecondWord'
你需要CASE
检查你是否在字符串的开头,在这种情况下你不需要前面的位置,因为那是0.
我会对这段代码做一些其他改进:LEN
可以计算一次,我们也可以将 [BACKSPACE]
值存储在一个变量中
DECLARE @inputString NVARCHAR(MAX);
SET @inputString = 'Word[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]sgred[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]SecondWord';
DECLARE @bspace nvarchar(50) = '[BACKSPACE]';
DECLARE @len int = LEN(@bspace);
WITH rCTE AS(
SELECT V.YourColumn,
STUFF(V.YourColumn,CHARINDEX(@bspace,V.YourColumn)-1,@len+1,'') AS ReplacedColumn,
1 AS Iteration
FROM (VALUES(@inputString))V(YourColumn)
UNION ALL
SELECT r.YourColumn,
CASE WHEN CHARINDEX(@bspace,r.ReplacedColumn) = 1
THEN STUFF(r.ReplacedColumn,1,@len,'')
ELSE STUFF(r.ReplacedColumn,CHARINDEX(@bspace,r.ReplacedColumn)-1,@len+1,'')
END,
r.Iteration + 1
FROM rCTE r
WHERE CHARINDEX(@bspace,r.ReplacedColumn) > 0)
SELECT TOP (1) WITH TIES
r.YourColumn,
r.ReplacedColumn
FROM rCTE r
ORDER BY ROW_NUMBER() OVER (PARTITION BY r.YourColumn ORDER BY r.Iteration DESC);
以下代码归功于@Larnu,如果重复单词“[BACKSPACE]”之前不再有字符,如何修改此代码以不生成空值。我相信空值的出现是因为 CHARINDEX()
函数在重复出现的 [BACKSPACE] 单词之前不再有字符时产生负值。该解决方案需要与 SQL Server 2008 兼容。
最终目标是凡是有[BACKSPACE]的地方,如果[BACKSPACE]前面有字符,就去掉;否则,不要尝试删除之前的字符。
DECLARE @inputString NVARCHAR(MAX);
SET @inputString = 'Word[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]sgred[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]SecondWord';
WITH rCTE AS(
SELECT V.YourColumn,
STUFF(V.YourColumn,CHARINDEX('[BACKSPACE]',V.YourColumn)-1,LEN('[BACKSPACE]')+1,'') AS ReplacedColumn,
1 AS Iteration
FROM (VALUES(@inputString))V(YourColumn)
UNION ALL
SELECT r.YourColumn,
STUFF(r.ReplacedColumn,CHARINDEX('[BACKSPACE]',r.ReplacedColumn)-1,LEN('[BACKSPACE]')+1,''),
r.Iteration + 1
FROM rCTE r
WHERE CHARINDEX('[BACKSPACE]',r.ReplacedColumn) > 0)
SELECT TOP (1) WITH TIES
r.YourColumn,
r.ReplacedColumn
FROM rCTE r
ORDER BY ROW_NUMBER() OVER (PARTITION BY r.YourColumn ORDER BY r.Iteration DESC);
期望的输出是'SecondWord'
你需要CASE
检查你是否在字符串的开头,在这种情况下你不需要前面的位置,因为那是0.
我会对这段代码做一些其他改进:LEN
可以计算一次,我们也可以将 [BACKSPACE]
值存储在一个变量中
DECLARE @inputString NVARCHAR(MAX);
SET @inputString = 'Word[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]sgred[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]SecondWord';
DECLARE @bspace nvarchar(50) = '[BACKSPACE]';
DECLARE @len int = LEN(@bspace);
WITH rCTE AS(
SELECT V.YourColumn,
STUFF(V.YourColumn,CHARINDEX(@bspace,V.YourColumn)-1,@len+1,'') AS ReplacedColumn,
1 AS Iteration
FROM (VALUES(@inputString))V(YourColumn)
UNION ALL
SELECT r.YourColumn,
CASE WHEN CHARINDEX(@bspace,r.ReplacedColumn) = 1
THEN STUFF(r.ReplacedColumn,1,@len,'')
ELSE STUFF(r.ReplacedColumn,CHARINDEX(@bspace,r.ReplacedColumn)-1,@len+1,'')
END,
r.Iteration + 1
FROM rCTE r
WHERE CHARINDEX(@bspace,r.ReplacedColumn) > 0)
SELECT TOP (1) WITH TIES
r.YourColumn,
r.ReplacedColumn
FROM rCTE r
ORDER BY ROW_NUMBER() OVER (PARTITION BY r.YourColumn ORDER BY r.Iteration DESC);