Najlepszy sposób na wyodrębnienie segmentów / wartości z pola VARCHAR w SQL opartym na SET
Weź następujące przykładowe dane:
SELECT 'HelpDesk Call Reference F0012345, Call Update, 40111' AS [Subject]
UNION ALL
SELECT 'HelpDesk Call Reference F0012346, Call Resolved, 40112' AS [Subject]
UNION ALL
SELECT 'HelpDesk Call Reference F0012347, New call logged, 40113' AS [Subject]
To, co chciałbym zrobić, to wyodrębnić te dane w następujący sposób:
Jak widać, muszę wyodrębnić Ref, Type & OurRef jako oddzielne kolumny, aby zapewnić efektywny zestaw SQL oparty na zestawie podczas przetwarzania wynikowych wiadomości e-mail.
Zazwyczaj w tym scenariuszu używałbym funkcji takiej jak ta:
CREATE FUNCTION dbo.fnParseString (
@Section SMALLINT ,
@Delimiter CHAR ,
@Text VARCHAR(MAX)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @NextPos SMALLINT;
DECLARE @LastPos SMALLINT;
DECLARE @Found SMALLINT;
SELECT @NextPos = CHARINDEX(@Delimiter, @Text, 1) ,
@LastPos = 0 ,
@Found = 1
WHILE @NextPos > 0
AND ABS(@Section) <> @Found
SELECT @LastPos = @NextPos ,
@NextPos = CHARINDEX(@Delimiter, @Text, @NextPos + 1) ,
@Found = @Found + 1
RETURN LTRIM(RTRIM(CASE
WHEN @Found <> ABS(@Section) OR @Section = 0 THEN NULL
WHEN @Section > 0 THEN SUBSTRING(@Text, @LastPos + 1, CASE WHEN @NextPos = 0 THEN DATALENGTH(@Text) - @LastPos ELSE @NextPos - @LastPos - 1 END)
ELSE SUBSTRING(@Text, @LastPos + 1, CASE WHEN @NextPos = 0 THEN DATALENGTH(@Text) - @LastPos ELSE @NextPos - @LastPos - 1 END)
END))
END
Na przykład i zastąpię białą spację przed ref, aby dołączyć przecinek i podzielić w następujący sposób:
WITH ExampleData
AS ( SELECT 'HelpDesk Call Reference F0012345, Call Update, 40111' AS [Subject]
UNION ALL
SELECT 'HelpDesk Call Reference F0012346, Call Resolved, 40112'
UNION ALL
SELECT 'HelpDesk Call Reference F0012347, New call logged, 40113'
)
SELECT dbo.fnParseString(2, ',', REPLACE([Subject], 'HelpDesk Call Reference ', 'HelpDesk Call Reference, ')) AS [Ref] ,
dbo.fnParseString(3, ',', REPLACE([Subject], 'HelpDesk Call Reference ', 'HelpDesk Call Reference, ')) AS [Type] ,
dbo.fnParseString(4, ',', REPLACE([Subject], 'HelpDesk Call Reference ', 'HelpDesk Call Reference, ')) AS [OurRef]
FROM ExampleData
Jak widzisz, mam rozwiązanie, które pozwala uzyskać wynik końcowy, ale użycie niechlujnego udf nie jest idealne i zastanawiałem się, czysql-server ma lepszy sposób na robienie takich rzeczy - być może wbudowane wyrażenia regularne? To znaczy. MyślęPATINDEX()
akceptuje wyrażenia regularne jako ciąg wyszukiwania - w połączeniu zSUBSTRING()
mógłbym robić to, czego potrzebuję, ale naprawdę nie wiem od czego zacząć?
Edytować: Proszę zauważyć, że jest to uproszczony przykład, temat jest zmienny i dostosuję tę samą technikę do analizowania ciała, ciało będzie miało 8 elementów danych, które muszę przeanalizować przy użyciu różnych ograniczników, więc to wyklucza użycieParseName()
ponieważ pozwala tylko na 4 części i nie mogę użyć stałej długości (tj.substring()
) ponieważ długość będzie bardzo zróżnicowana (szczególnie, jeśli zaangażowane są różne centra informacyjne), dlatego właśnie myślałemPATINDEX()
& SUBSTRING()