我需要一个在破折号输入字符串中输出第一个N个字符的函数。
需求:
如果N落在一个单词的中间,即使总数超过N,也要在输出中包括最后一个单词
如果输出以“-”和LEN(output)== N结尾,则包括下一个单词
示例:(N = 70)
declare @Text varchar(1000) = 'this-is-product-url-prepared-for-better-Google-Search-Engnine-SEO-totalLength-should-be-70-characters'
我已经采用了前70个字符,因此得到以下结果(我删除了结尾的破折号-在此处未包括的单独步骤中:]
SELECT LEFT(@Text + '-', CHARINDEX('-',@Text, 70))
this-is-product-url-prepared-for-better-Google-Search-Engnine-SEO-tot
在这种情况下,我需要一个返回以下内容的函数:
this-is-product-url-prepared-for-better-Google-Search-Engnine-SEO-totalLength
任何解决方案将不胜感激。
更新后的答案:修正了您的表情
这将起作用,并且基于@Lukstroms发布的内容;他不满足您的第二个要求(当@N是连字符的位置时。)
SELECT SUBSTRING(@Text,1,CHARINDEX('-',@Text,@N+1)-1);
上一个答案:
这是使用ngrams8k的方法,这将处理@N代表单词中间或破折号-
的情况。
DECLARE
@Text VARCHAR(1000) = 'this-is-product-url-prepared-for-better-Google-Search-Engnine-SEO-totalLength-should-be-70-characters',
@N INT = 70;
SELECT SUBSTRING(@Text,0,MAX(ng.nxt))
FROM
(
SELECT ng.position, nxt = LEAD(ng.Position,1) OVER (ORDER BY ng.Position), ng.Token
FROM samd.ngrams8k(@Text,1) AS ng
WHERE ng.Token = '-'
) AS ng
WHERE ng.Position <= @N;
最终更新(有关N-GRAMS的注意)
正如Martin正确提到的那样,N-Grams解决方案过于复杂,但我急于解决该问题,无法修复OP的原始CHARINDEX表达式。就是说,ngrams8k解决方案令人讨厌的快速允许大量的灵活性。
例如,要求包含一个上限和下限参数;例如我们需要所有between first连字符高于@Low
和last连字符低于@High
。可以通过对上述答案进行细微调整来解决此问题。
DECLARE
@Text VARCHAR(1000) = 'this-is-product-url-prepared-for-better-Google-Search-Engnine-SEO-totalLength-should-be-70-characters',
@Low INT = 16,
@high INT = 70;
SELECT NewString = SUBSTRING(@Text,MIN(ng.position)+1, MAX(ng.nxt)-MIN(ng.position)-1)
FROM
(
SELECT ng.position, nxt=LEAD(ng.Position,1) OVER (ORDER BY ng.Position)
FROM samd.ngrams8k(@Text,1) AS ng
WHERE ng.Token = '-'
) AS ng
WHERE ng.Position <= @high AND ng.Position > @low;
返回:
prepared-for-better-Google-Search-Engnine-SEO-totalLength