Извлечение строки между двумя символами в SQL - PullRequest
0 голосов
/ 10 мая 2019

У меня проблемы с извлечением выделенных символов из строки

Вот фрагмент значений из поля с именем 'TXT':

  • FNP, 10/09/2018, PO-00123456 - F333330- FA_002056
  • FNP, 18-09-2018, PO-00987654 - F010122-FA_002056
  • FNP, 28.12.2017, PO-00123987 - F10101
  • FNP, 13-03-2019, FRPO-35412 - F27272-ANNUL PO

И я хочу извлечь F333330, F010122, F10101 и F27272

Я экспериментировал с charindex, left / right и подстрокой, но не смог его взломать

SELECT TXT , 
CASE WHEN CHARINDEX('-',(SUBSTRING(txt,CHARINDEX('-',txt,2)+1,99)))=0
THEN 
LTRIM(RTRIM(SUBSTRING(txt,CHARINDEX('-',txt,2)+1,99)))
ELSE 
LTRIM(RTRIM(SUBSTRING(txt,CHARINDEX('-',txt,2) +1,CHARINDEX('-',SUBSTRING(txt,CHARINDEX('-',txt,2)+1,99))-1)))
END
FROM #test

Мой желаемый набор строк должен просто показывать:

  • F333330
  • F010122
  • F10101
  • F27272

Я пробовал другие варианты подстроки без указания регистра, но безуспешно. Кто-нибудь может помочь?

Спасибо, Nuems

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Вот один вариант с использованием parsename() и CROSS APPLY

Пример

Declare @YourTable table (Txt varchar(500))
Insert Into @YourTable values
('FNP, 10/09/2018,PO-00123456 - F333330- FA_002056')
,('FNP, 18-09-2018,PO-00987654 - F010122- FA_002056')
,('FNP, 28/12/2017,PO-00123987 - F10101')
,('FNP, 13-03-2019,FRPO-35412 - F27272-ANNUL PO')

Select A.Txt
      ,NewValue = case when parsename(S,3) is null then parsename(S,1) else parsename(S,2) end
 From  @YourTable A
 Cross Apply (values ( replace(replace(parsename(replace(TXT,',','.'),1),'PO-','PO'),'-','.') )) B(S)

Возвращает

Txt                                                  NewValue
FNP, 10/09/2018,PO-00123456 - F333330- FA_002056     F333330
FNP, 18-09-2018,PO-00987654 - F010122- FA_002056     F010122
FNP, 28/12/2017,PO-00123987 - F10101                 F10101
FNP, 13-03-2019,FRPO-35412 - F27272-ANNUL PO         F27272
0 голосов
/ 10 мая 2019

Я знаю, что немного опоздал, но вот быстрый и эффективный способ сделать это, предполагая, что текст начинается с F, и вы знаете минимальную / максимальную длину хороших значений.В этом примере я предполагаю, что значение будет длиной 5-7 символов, но это можно легко настроить.

DECLARE @YourTable table (SomeId INT IDENTITY PRIMARY KEY, Txt varchar(500))
Insert Into @YourTable values
('FNP, 10/09/2018,PO-00123456 - F333330- FA_002056')
,('FNP, 18-09-2018,PO-00987654 - F010122- FA_002056')
,('FNP, 28/12/2017,PO-00123987 - F10101')
,('FNP, 13-03-2019,FRPO-35412 - F27272-ANNUL PO')


SELECT 
  t.SomeID, 
  ItemLength = MAX(r.N), 
  ItemIndex  = MAX(p.P),
  Item       = SUBSTRING(MAX(t.Txt),MAX(p.P),MAX(r.N)+1)
FROM @YourTable AS t
CROSS JOIN  (VALUES(4),(5),(6))                          AS r(N)
CROSS APPLY (VALUES('%F'+REPLICATE('[0-9A-Z]',r.N)+'%')) AS f(P)
CROSS APPLY (VALUES(PATINDEX(f.P,t.Txt)))                AS p(P)
WHERE p.P > 0
GROUP BY t.SomeId

Возвращает:

SomeID      ItemLength  ItemIndex   Item
----------- ----------- ----------- ---------
1           6           31          F333330
2           6           31          F010122
3           5           31          F10101
4           5           30          F27272
0 голосов
/ 10 мая 2019

Попробуйте это?

DECLARE @test TABLE (TXT VARCHAR(500));
INSERT INTO @test SELECT 'FNP, 10/09/2018,PO-00123456 - F333330- FA_002056' UNION ALL
SELECT 'FNP, 18-09-2018,PO-00987654 - F010122- FA_002056' UNION ALL
SELECT 'FNP, 28/12/2017,PO-00123987 - F10101' UNION ALL 
SELECT 'FNP, 13-03-2019,FRPO-35412 - F27272-ANNUL PO';
SELECT SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, CASE WHEN CHARINDEX('-', SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 99)) = 0 THEN 99 ELSE CHARINDEX('-', SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 99)) - 1 END)
FROM @test;

... или с этим одним дополнительным рядом:

DECLARE @test TABLE (TXT VARCHAR(500));
INSERT INTO @test SELECT 'FNP, 10/09/2018,PO-00123456 - F333330- FA_002056' UNION ALL
SELECT 'FNP, 18-09-2018,PO-00987654 - F010122- FA_002056' UNION ALL
SELECT 'FNP, 28/12/2017,PO-00123987 - F10101' UNION ALL 
SELECT 'FNP, 13-03-2019,FRPO-35412 - F27272-ANNUL PO' UNION ALL
SELECT 'FNP, 11/10/2017,PO-00112311 - F32121 regul po 112311';
SELECT SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 
    CASE 
        WHEN CHARINDEX('-', SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 99)) != 0 THEN CHARINDEX('-', SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 99)) - 1 
        WHEN CHARINDEX(' ', SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 99)) != 0 THEN CHARINDEX(' ', SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 99)) - 1 
        ELSE 99
    END)
FROM @test;

... или бонус с меньшим количеством повторений (использует CTE):

WITH x AS (
    SELECT SUBSTRING(TXT, PATINDEX('%- F%', TXT) + 2, 99) AS TXT FROM @test)
SELECT SUBSTRING(TXT, 0, 
    CASE 
        WHEN CHARINDEX('-', TXT) != 0 THEN CHARINDEX('-', TXT) - 1
        WHEN CHARINDEX(' ', TXT) != 0 THEN CHARINDEX(' ', TXT) - 1
        ELSE 99
    END)
FROM x;
...