在字符串中查找文本的行和位置

时间:2019-01-26 21:06:29

标签: sql sql-server

我需要获取文本中特定单词的行号和位置(在该行上)。

例如:

--
This is my first line.
This is my second line.
--

如果我要检查“秒”,我应该得到类似“ 2,12

的信息。

有任何建议吗?

2 个答案:

答案 0 :(得分:3)

假设您要查找每行的第一个匹配项,并假设LINE由char(13)而不是标点符号分隔。

示例

Declare @YourTable table (ID int,SomeText varchar(max))
Insert Into @YourTable values
(1,'This is my first line.
This is my second line.')
,(2,'This another but has a second note
Which not related to the prior "second" note')

Declare @Search varchar(100)='second'

Select A.ID
      ,Position=concat(RetSeq,',',charindex(@Search,RetVal))
 From  @YourTable A
 Cross Apply (
                Select RetSeq = row_number() over (order by 1/0)
                      ,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
                From  (Select x = Cast('<x>' + replace((Select replace(replace(SomeText,char(10),''),char(13),'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                Cross Apply x.nodes('x') AS B(i)
              ) B
 Where charindex(@Search,RetVal)>0

返回

ID  Position
1   2,12
2   1,24
2   2,33
  

编辑-请求的编辑

Select Top 1 with Ties
       A.ID
      ,Position=concat(RetSeq,',',charindex(@Search,RetVal))
 From  @YourTable A
 Cross Apply (
                Select RetSeq = row_number() over (order by 1/0)
                      ,RetVal = B.i.value('(./text())[1]', 'varchar(max)')
                From  (Select x = Cast('<x>' + replace((Select replace(replace(SomeText,char(10),''),char(13),'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                Cross Apply x.nodes('x') AS B(i)
              ) B
 Where charindex(@Search,RetVal)>0
 Order by Row_Number() over (Partition By ID Order by RetSeq)

返回

ID  Position
1   2,12
2   1,24

答案 1 :(得分:0)

这里是不使用子查询的替代解决方案;它依赖于SQL Server string functions,例如OrdCHARINDEX

REVERSE

原理是首先找到搜索到的字符串(SELECT CASE WHEN CHARINDEX( @match, t.value ) < CHARINDEX( CHAR(10), t.value ) THEN CONCAT( '1,', CHARINDEX( @match, t.value ) ) ELSE CONCAT( LEN(LEFT(t.value, CHARINDEX(@match, t.value))) - LEN(REPLACE(LEFT(t.value, CHARINDEX(@match, t.value)), CHAR(10), '')) + 1, ',', CHARINDEX (CHAR(10), REVERSE(LEFT(t.value, CHARINDEX(@match, t.value)))) - 1 ) END from t; )的位置,然后计算上一个回车符(@match的位置-根据情况也可以是CHAR(10)您的EOF设置),使用CHAR(13)。有了这两个值,我们就可以计算出匹配在行上的位置以及行号(为此,我们将子字符串的长度比较,直到匹配与其没有回车符的长度为止)。当比赛在第一行时,必须格外小心。

db <>提琴here

REVERSE

 | (No column name) |
 | :--------------- |
 | 2,12             |