SQL Server 从字符串中提取多个值并对其进行排序

qoefvg9y  于 2022-12-22  发布在  其他
关注(0)|答案(2)|浏览(163)

我在Notes字段中有一些值,这些值如下所示,其中abc表示不同的单词:

申请说明:VAR - abc abc abc abc abc

不幸的是,数据存储方式的设计非常糟糕,我需要为每个“Required Notes:“记录提取Note Type,还需要从最近到最早排序(字符串的最后一部分到字符串的第一部分)。

CREATE TABLE #TestData
(
    ClientID int,
    Notes varchar(8000)
)
insert into #TestData
(
    ClientID,
    Notes
)
select
    1,
    'Request Notes: VAR - abc abc abc abc abc'
union all
select
    2,
    'Request Notes: OZR - abc abc abc abc abc Request Notes: ACC - abc abc abc abc abc Request Notes: TYU - abc abc abc abc abc'
union all
select
    3,
    'Request Notes: TYU - abc abc abc abc abc Request Notes: VAR - abc abc abc abc abc'

这就是我期望上面例子的输出:

--Expected Output

Client ID       Type    Order
1               VAR     1
2               TYU     1
2               ACC     2
2               OZR     3
3               VAR     1
3               TYU     2

到目前为止,我已经完成了提取OZR的工作,但是我对如何获取其他的并将列表排序为上面的预期输出感到困惑。

DECLARE @Text varchar(500) = 'Request Notes: OZR - abc abc abc abc abc Request Notes: ACC - abc abc abc abc abc Request Notes: TYU - abc abc abc abc abc'

SELECT TRIM(REPLACE(REPLACE(SUBSTRING(@Text, CHARINDEX(':', @Text), CHARINDEX('-',@text) - CHARINDEX(':', @Text) + Len('-')),':',''),'-',''))
7d7tgy0s

7d7tgy0s1#

您可以使用 openjson 将数据提取为数组和过滤器:

select d.ClientId, n.*
from #testdata d
cross apply (
  select 
    Left(j.[value],3) [Type],
    Row_Number() over(order by Convert(int,j.[key]) desc) [Order] 
  from OpenJson(Concat('["',replace(notes,'Notes: ', '","'),'"]')) j
  where j.[value] != 'Request'
 )n;

示例Fiddle

jfewjypa

jfewjypa2#

这是一个递归的CTE版本。它根据“Request Notes:“拆分字符串,然后执行左/右组合以提取3个字母的代码。它在构建订单时迭代订单。然后从CTE中进行选择,并只取有一些NotesRemainder的行:

;
WITH CTESplit
AS (
    SELECT ClientID,
           RIGHT(LEFT(Notes, CHARINDEX('Request Notes:', Notes) + 17), 3) AS NotesPart,
           RIGHT(Notes, LEN(Notes) - CHARINDEX('Request Notes:', Notes) - 17) AS NotesRemainder,
           -1 AS [Order]
    FROM #TestData
    WHERE Notes IS NOT NULL AND CHARINDEX('Request Notes:', Notes) > 0
    UNION ALL
    SELECT CTESplit.ClientID,
           RIGHT(LEFT(CTESplit.NotesRemainder, CHARINDEX('Request Notes:', CTESplit.NotesRemainder) + 17), 3),
           RIGHT(CTESplit.NotesRemainder, LEN(CTESplit.NotesRemainder) - CHARINDEX('Request Notes:', CTESplit.NotesRemainder)),
           CTESplit.[Order] - 1
    FROM CTESplit
    WHERE CTESplit.NotesRemainder IS NOT NULL AND CHARINDEX('Request Notes:', CTESplit.NotesRemainder) > 0
    UNION ALL
    SELECT CTESplit.ClientID,
           RIGHT(LEFT(CTESplit.NotesRemainder, CHARINDEX('Request Notes:', CTESplit.NotesRemainder) + 17), 3),
           NULL,
           CTESplit.[Order] - 1
    FROM CTESplit
    WHERE CTESplit.NotesRemainder IS NOT NULL AND CHARINDEX('Request Notes:', CTESplit.NotesRemainder) = 0
)
SELECT CS.ClientID,
       CS.NotesPart AS Type,
       CS.[Order] +(SELECT MIN([Order])*-1 FROM CTESplit WHERE ClientID = CS.ClientID) AS [Order]
FROM CTESplit AS CS
WHERE CS.NotesRemainder IS NOT NULL
ORDER BY CS.ClientID,
         CS.[Order] ASC;

相关问题