我如何从短划线分隔的字符串中返回前N个以完整单词结尾的字符?

问题描述 投票:0回答:1

我需要一个在破折号输入字符串中输出第一个N个字符的函数。

需求

  1. 如果N落在一个单词的中间,即使总数超过N,也要在输出中包括最后一个单词

  2. 如果输出以“-”和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

任何解决方案将不胜感激。

sql-server tsql
1个回答
0
投票

更新后的答案:修正了您的表情

这将起作用,并且基于@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连字符高于@Lowlast连字符低于@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
© www.soinside.com 2019 - 2024. All rights reserved.