Правильный метод для разбора строки в SQL - PullRequest
0 голосов
/ 15 октября 2018

У меня есть строка в следующем формате:

C Aleksander Barkov C Nico Hischier UTIL Tyson Jost W Taylor Hall W Evgenii Dadonov W Kyle Palmieri D Kris Letang D Ryan Suter G Casey DeSmith

Мне нужно выделить имена между каждой заглавной буквой (и UTIL).Логика состоит в том, чтобы извлечь содержимое между каждым capitalized letter, включая слово UTIL.

, чтобы конечный результат был, например:

'Aleksander Barkov', 
'Nico Hischier', 
'Tyson Jost', 
'Taylor Hall', 
etc

Любые идеи о том, как это сделатьэто?

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Просто еще один вариант, если вы не можете использовать решение Алана через nGram (+1)

Сначала мы выполняем грубую замену, создавая строку с разделителями, затем мы анализируем эту строку с разделителями, используя небольшой XML

Пример

Declare @S varchar(max) = 'C Aleksander Barkov C Nico Hischier UTIL Tyson Jost W Taylor Hall W Evgenii Dadonov W Kyle Palmieri D Kris Letang D Ryan Suter G Casey DeSmith'

Select @S = ltrim(replace(' '+@S COLLATE SQL_Latin1_General_CP1_CS_AS,C,'|'))  
 From (Select Top 26 C=' '+char(64+Row_Number() Over (Order By (Select NULL)))+' ' From master..spt_values n1  
       Union All
       Select ' UTIL '   -- Note We add "UTIL" to the list
      )  A 

Select RetSeq = Row_Number() over (Order By (Select null))
      ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From  (Select x = Cast('<x>' + replace(substring(@S,2,len(@S)),'|','</x><x>')+'</x>' as xml).query('.')) as A 
Cross Apply x.nodes('x') AS B(i)

Возвращает

RetSeq  RetVal
1       Aleksander Barkov
2       Nico Hischier
3       Tyson Jost
4       Taylor Hall
5       Evgenii Dadonov
6       Kyle Palmieri
7       Kris Letang
8       Ryan Suter
9       Casey DeSmith
0 голосов
/ 15 октября 2018

Так что возьмите копию NGrams8K .Затем вы можете сделать это:

-- sample data
DECLARE @string VARCHAR(8000) = 
'C Aleksander Barkov C Nico Hischier UTIL Tyson Jost W Taylor Hall W Evgenii Dadonov W Kyle Palmieri D Kris Letang D Ryan Suter G Casey DeSmith';

-- my solution works except for cases where the upper-case word is more than one char. You'll need to iron that out
SET @string = REPLACE(@string, 'UTIL', 'U');

-- solution
SELECT SUBSTRING(@string, d.pos+2, d.nextPos-d.pos-3)
FROM 
(
  SELECT 
    pos     = ng.position,
    nextPos = LEAD(ng.position,1,8000) OVER (ORDER BY ng.position)
  FROM   samd.ngrams8K(@string, 2) AS ng
  WHERE  ng.token COLLATE Latin1_General_BIN LIKE '[A-Z] '
) AS d;

Возвращает:

name
------------------
Aleksander Barkov
Nico Hischier
Tyson Jost
Taylor Hall
Evgenii Dadonov
Kyle Palmieri
Kris Letang
Ryan Suter
Casey DeSmith

Обратите внимание, что для случаев, когда у вас есть все заглавные слова с> 1 символом, вы будетедолжен обновить свою логику.

Обновление (на основе вопроса в комментариях):

Для строки, отформатированной следующим образом (обратите внимание, я опустил последний разделитель): | Eri | Staal | Нико Хишер| Митчелл Марнер | Тейлор Холл | Кайл Палмиери | Джейсон Цукер | Райан Сутер | Уилл Батчер | Кит Кинкейд

Вы можете изменить мой запрос так, чтобы он выглядел так:

DECLARE 
  @string VARCHAR(8000) = '|Eri|Staal|Nico Hischier|Mitchell Marner|Taylor Hall|Kyle Palmieri|Jason Zucker|Ryan Suter|Will Butcher|Keith Kinkaid',
  @delimiter CHAR(1)    = '|';

SELECT 
  sortKey = ng.position, 
  [name]  = SUBSTRING
            (
              @string,
              ng.position+1,
              LEAD(ng.position,1,8000) OVER (ORDER BY ng.position)-ng.position-1
              --ISNULL(NULLIF(CHARINDEX(@delimiter,@string,ng.position+1),0),8000)-ng.position-1
            )
FROM  samd.NGrams8K(@string, 1) AS ng
WHERE token = @delimiter;

Обратите внимание, что логикаВыше используется LEAD, для которого требуется SQL Server 2012+, если вы используете 2008, вы бы раскомментировали строку под ней и удалили строку, которая использует LEAD.Также обратите внимание, что это решение является уменьшенной версией DelimitedSplit8K (решение 2008 года) и DelimitedSplit8k_LEAD (версия, использующая LEAD).

Все это говорит - Если у вас есть контроль над форматом, почему бы не сохранить записи в 3NF ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...