I have values within a Notes field consisting of values such as this where abc represents different words:
Request Notes: VAR - abc abc abc abc abc
Unfortunately the design of how the data is stored is very poor, and I need to pull out the Note Type for each "Required Notes:" record. It also needs ordering from most recent to oldest (last part of the string to first part of the string).
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'
This is how I expect the output to be for the above examples:
--Expected Output
Client ID Type Order
1 VAR 1
2 TYU 1
2 ACC 2
2 OZR 3
3 VAR 1
3 TYU 2
I have this together so far which extracts OZR, but I'm stumped on how to get the others and order the list into the expected output above.
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('-')),':',''),'-',''))
CodePudding user response:
You can use openjson to extract your data as an array and filter:
select d.ClientId, n.*
from #testdata d
cross apply (
select
Left(j.[value],3) [Type],
Row_Number() over(order by Convert(int,j.[key])) [Order]
from OpenJson(Concat('["',replace(notes,'Notes: ', '","'),'"]')) j
where j.[value] != 'Request'
)n;
Example Fiddle
CodePudding user response:
Here's a recursive CTE version. It splits the string based on finding "Request Notes:" then does a left/right combo to extract the 3 letter code. It iterates the order as it builds. Then you select from the CTE and only take rows where there's some 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 CTESplit.ClientID,
CTESplit.NotesPart AS Type,
CTESplit.[Order]
FROM CTESplit
WHERE CTESplit.NotesRemainder IS NOT NULL
ORDER BY CTESplit.ClientID,
CTESplit.[Order] DESC;