Как выбрать строку переменной длины из двух известных строк в SQL Server в VARCHAR (MAX), где некоторые столбцы не имеют применимых строк - PullRequest
0 голосов
/ 05 ноября 2018

Используя SQL Server 2012, мне нужно получить из этого примера

ColumnName    
--------------------------------
 Enroll to: Carol Goals are many and varied  
 characters that don't include desired results
 Enroll to: Jan Levinson Goals will be discussed at first encounter
 Enroll to: Stephon-Anderson   Goals none
 NULL
 Enroll to:   David   Goals  --Note uneven spaces, Need David 

чтобы извлечь столбец, похожий на:

Name    
-----------
Carol
NULL   
Jan Levinson   
Stephon-Anderson 
NULL 
David 

Этот код приблизил меня к результатам, которые я искал, но иногда неправильно обрезал имя.

Select 
CASE WHEN AssignedTo like '%Enroll To:%' THEN  SUBSTRING(AssignedTo, CHARINDEX('%Enroll To:%', AssignedTo) + LEN('%Enroll To:%') 
            ,CHARINDEX('Goals', AssignedTo) - CHARINDEX('%Enroll To:%', AssignedTo) + LEN('Goals'))
          ELSE 'None'
          END AS 'Name'
FROM
(

  Select 
CASE WHEN ColumnName like '%Enroll To:%' THEN SUBSTRING    (ColumnName, CHARINDEX('Enroll To:', ColumnName), 40) 


ELSE 'None'
END AS 'AssignedTo'

FROM TABLE ) A

Я не могу тебя отблагодарить!

Ответы [ 4 ]

0 голосов
/ 07 ноября 2018

Вот ваши данные для проверки в виде таблицы:

declare @goals table (string nvarchar(255));
insert @goals values 
    ('Enroll to: Carol Goals are many and varied  characters that don''t include desired results'),
    ('Enroll to: Jan Levinson Goals will be discussed at first encounter'),
    ('Enroll to: Stephon-Anderson   Goals none'),
    (NULL),
    ('Enroll to:   David   Goals  '), --Note uneven spaces, Need David 
    (' '); -- I (psw) added this

И следующий код, кажется, делает то, что вы хотите без ошибок. Но предполагается, что ваше предложение после имени всегда будет начинаться с «Цели».

select      *,
            result = 
                case 
                when isValid = 1 then 
                    ltrim(rtrim(
                        substring(string, colonPos + 1, goalsPos - colonPos - 1)
                    ))
                end

from        @goals
cross apply (select 
                colonPos = charindex(':', string),
                goalsPos = patIndex('%goals%', string)
            ) positions
cross apply (select
                isValid = 
                    case 
                    when colonPos = 0 or goalsPos = 0 or colonPos > goalsPos then 0
                    else 1
                    end
            ) validity
0 голосов
/ 05 ноября 2018

Вот альтернатива ответу Гордона:

SELECT
    SUBSTRING(ColumnName,
              CHARINDEX(':', ColumnName) + 2,
              CHARINDEX(' ', ColumnName, CHARINDEX(':', ColumnName) + 2) -
                  CHARINDEX(':', ColumnName) - 2) AS Name
FROM yourTable;

Демо

0 голосов
/ 06 ноября 2018

Это дало желаемый результат и, похоже, имеет дело с переменной длиной целевой строки. Надеюсь, это кому-нибудь поможет.

DECLARE @pretext as NVARCHAR(100) = 'Enroll to:' 
DECLARE @posttext as NVARCHAR(100) = 'Goals'

Select 
,CASE When CHARINDEX(@posttext, ColumnName) - (CHARINDEX(@pretext, ColumnName) + len(@pretext)) < 0 THEN NULL
    Else
    SUBSTRING(ColumnName, CHARINDEX(@pretext, ColumnName) + len(@pretext)
    ,CHARINDEX(@posttext, ColumnName) - (CHARINDEX(@pretext, ColumnName) + len(@pretext)) )    
    END as betweentext 

FROM TABLE 
0 голосов
/ 05 ноября 2018

Вы можете использовать apply и строковые функции:

select left(v.s1, charindex(' ', s1) - 1)
from t cross apply
     (values (stuff(t.col, 1, 11, '')) v(s1) 
...