Как извлечь текст из строки между известными символами, если символы появляются более одного раза - PullRequest
0 голосов
/ 15 мая 2019

У меня есть текст, который включает, например, #(sharp) символ. Строка содержит параметры. Параметры начинаются с # и заканчиваются #.

declare @TEXT varchar(200) = 'Dear #NAMEOFGUEST# , we glad to see youSOMEHOTEL tomorrow.' 
declare @scanChar char(1)='#'


select
    SUBSTRING(@TEXT, CHARINDEX(@scanChar, @TEXT) + 1, (((LEN(@TEXT)) - CHARINDEX(@scanChar, REVERSE(@TEXT))) - CHARINDEX(@scanChar, @TEXT)))

Return:

NAMEOFGUEST

Это правильный результат.

Когда строка содержит только один параметр #NAMEOFGUEST#, это работает. Если мы добавим SOMEHOTEL в #, то как #SOMEHOTEL# результат будет не таким, как мы хотим.

 declare @TEXT varchar(200) = 'Dear #NAMEOFGUEST# , we glad to see you #SOMEHOTEL# tomorrow.' 
 declare @scanChar char(1)='#'

Возвращает:

 NAMEOFGUEST# , we glad to see you #SOMEHOTEL

Я хочу получить тот же результат, что и в предыдущем примере, например NAMEOFGUEST * только 1021 *.

Ответы [ 2 ]

3 голосов
/ 15 мая 2019

Используя CHARINDEX(@FindString, @PrintData, CHARINDEX(@FindString, @PrintData) + 1), вы можете найти вторые вхождения #, после чего можно будет выполнить оставшиеся вычисления.

Следующий запрос будет работать.

DECLARE @PrintData AS VARCHAR (200) = 'Dear #NAMEOFGUEST# , we glad to see you #SOMEHOTEL# tomorrow.';
DECLARE @FindString AS CHAR (1) = '#';
DECLARE @LenFindString AS INT = LEN(@FindString);

SELECT SUBSTRING(@PrintData, 
 CHARINDEX(@FindString, @PrintData) + @LenFindString, 
 CHARINDEX(@FindString, @PrintData, CHARINDEX(@FindString, @PrintData) + 1) - (CHARINDEX(@FindString, @PrintData) + @LenFindString)
);     

Демонстрация по дб <> fiddle

0 голосов
/ 15 мая 2019

Вы можете использовать рекурсивный подход, например так:

A таблица-макет для имитации ориентированного на множество сценария

declare @tbl TABLE(ID INT IDENTITY, SomeComment VARCHAR(100),SomeString varchar(200));
INSERT INTO @tbl VALUES('3 Terms','Dear #NAMEOFGUEST# , we glad to see you #SOMEHOTEL# tomorrow. And even #AThirdOne# is here.')
                      ,('1 Term','Dear #NAMEOFGUEST# , we glad to see you soon.') 
                      ,('No Term','Dear Guest, nice to see you.')
                      ,('invalid 1','Dear Guest, nice to #see you.')
                      ,('invalid ?','Dear #Guest, nice# to see you.');
declare @scanChar char(1)='#';

- запрос

WITH recCTE AS
(
    SELECT t.ID
          ,t.SomeComment
          ,t.SomeString AS TextToWork
          ,1 AS TermIndex
          ,D.*
    FROM @tbl t
    OUTER APPLY(SELECT CHARINDEX(@scanChar,t.SomeString)) A(StartingAt)
    OUTER APPLY(SELECT CHARINDEX(@scanChar,t.SomeString,A.StartingAt+1)) B(EndingAt)
    OUTER APPLY(SELECT CASE WHEN A.StartingAt>0 AND B.EndingAt >0 THEN SUBSTRING(t.SomeString,A.StartingAt+1,B.EndingAt- A.StartingAt-1) END) C(TermCandidate)
    OUTER APPLY(SELECT A.StartingAt,B.EndingAt,C.TermCandidate,SUBSTRING(t.SomeString,B.EndingAt+1,1000) AS RestString) D

    UNION ALL

    SELECT t.ID
          ,t.SomeComment
          ,t.RestString 
          ,t.TermIndex+1
          ,D.*
    FROM recCTE t
    OUTER APPLY(SELECT CHARINDEX(@scanChar,t.RestString)) A(StartingAt)
    OUTER APPLY(SELECT CHARINDEX(@scanChar,t.RestString,A.StartingAt+1)) B(EndingAt)
    OUTER APPLY(SELECT CASE WHEN A.StartingAt>0 AND B.EndingAt >0 THEN SUBSTRING(t.RestString,A.StartingAt+1,B.EndingAt- A.StartingAt-1) END) C(TermCandidate)
    OUTER APPLY(SELECT A.StartingAt,B.EndingAt,C.TermCandidate,SUBSTRING(t.RestString,B.EndingAt+1,1000) AS RestString) D
    WHERE (LEN(t.RestString) - LEN(REPLACE(t.RestString,@scanChar,'')))%2=0 AND CHARINDEX(@scanChar,t.RestString)>0
)
SELECT ID
      ,SomeComment
      ,TermIndex
      --this will exclude "Guest, nice" due to the blank
      ,CASE WHEN CHARINDEX(' ',TermCandidate)>0 THEN NULL ELSE TermCandidate END AS Term 
FROM recCTE
ORDER BY ID,TermIndex;

Результат

+----+-------------+-----------+-------------+
| ID | SomeComment | TermIndex | Term        |
+----+-------------+-----------+-------------+
| 1  | 3 Terms     | 1         | NAMEOFGUEST |
+----+-------------+-----------+-------------+
| 1  | 3 Terms     | 2         | SOMEHOTEL   |
+----+-------------+-----------+-------------+
| 1  | 3 Terms     | 3         | AThirdOne   |
+----+-------------+-----------+-------------+
| 2  | 1 Term      | 1         | NAMEOFGUEST |
+----+-------------+-----------+-------------+
| 3  | No Term     | 1         | NULL        |
+----+-------------+-----------+-------------+
| 4  | invalid 1   | 1         | NULL        |
+----+-------------+-----------+-------------+
| 5  | invalid ?   | 1         | NULL        |
+----+-------------+-----------+-------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...