String searching output tranformated into rows

0

Cześć,

mam taki temat: jak z poniższej Actual Table dojść do Desired Output 1 i Desired Output 2.
Czy korzystając z PATINDEX można znaleźć kolejne wystąpienia?
Szukany ciąg znaków to zawsze '%[0-9][0-9].[0-9][0-9].[0-9][0-9]%'

Będę bardzo wdzięczny za każdą wskazówkę:).
Pozdrawiam,
Arek

.............

Actutal Table
Ticket Text
1 dsdsd ds545 dssd54 5dsd sd sd 22.44.62 dsfdsf fsfdvdfd 11.55.77 fdfd dsf4 544f 4fd 86.22.44

Desired Output 1
Ticket Text
1 22.44.62
1 11.55.77
1 86.22.44

Desired Output 2
Ticket Text
1 22.44.62 / 11.55.77 / 86.22.44

2

PATINDEX to dobry trop możesz napisać funkcje:


CREATE  FUNCTION [dbo].[parseTicketText]
                (@text varchar(200))
RETURNS varchar(200)
AS
BEGIN

declare @result varchar(200)
set @result = ''

while  patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text)>0
begin 
    set @result = @result + ' / ' + substring(@text,patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text),8)
    set @text = STUFF(@text, patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text), 8, '')
end

RETURN substring(@result,4,200)
END

GO

i użyc do otrzymania 2 outputu:

SELECT ticket,[dbo].[parseTicketText](TEXT) FROM TICKET

co do outputu 1 to jak masz wersje >=2016 to uzyj STRING_SPLIT https://docs.microsoft.com/en[...]sact-sql?view=sql-server-2017

Możesz też napisac funkcje:


CREATE  FUNCTION [dbo].[parseTicketTextToRows]
                (@text varchar(200))
RETURNS @RtnValue table
(
    Data varchar(8) NOT NULL
)
AS
BEGIN

while  patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text)>0
begin 
    insert into @RtnValue values (substring(@text,patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text),8))
    set @text = STUFF(@text, patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text), 8, '')
end

RETURN
END

GO

i użyć w zapytaniu:


select ticket, f.data as Text from ticket 
cross apply [dbo].[parseTicketTextToRows](ticket.text) f
0

Dziękuję Panczo.
Będę potrzebował chwilę aby przetrawić ten kod - jestem nowy w temacie.
Mam jednak pytanie - czy w takich sytuacjach nie stosuje się pętli (np. while)?
To nie jest pożądane w SQL rozwiązanie, że nikt go nie proponuje?

Pozdrawiam,
Arek

0

W tych funkcjach są pętle...

Pętle nie są złe, w tym konkretnym przypadku używam ich do wyciągnięcia danych z ciągu znaków. Słabe by to było jakbyśmy używali pętli/kursorów do wyciągania danych z tabel. Zresztą za kursory w robocie obcinam
ręce ;) W swojej wieloletniej praktyce nigdy nie spotkałem się z przypadkiem by były one potrzebne... Dodam tylko, że da się to zrobić stosując rekurencję, tak że nie będzie potrzeby tworzenia dodatkowych obiektów na bazie...

0

Dziękuję, wszystko pięknie działa. Mam jeszcze jedno pytanie w zakresie parseTicketTextToRows (czyli Desired Output2). Jak teraz bym chciał dodać kolejną kolumnę, która wyszukuje mi coś innego z tego samego @text to muszę stworzyć drugą analogiczną funkcję i zastosować drugie cross aply jak poniżej

SELECT ident, l.DATA AS LogDate, getdate() as CreationDay
FROM Tickets
CROSS apply dbo.parseTicketTextToRows(Text) e
CROSS apply dbo.parseLogDateToRows(Text) l

czy w już istniejące funkcji można to uzyskać?

Pozdrawiam,
Arek

0

Trudno odpowiedzieć jak nie wiem co masz zrobić, pewnie można rozbudować funkcje, lub napisać nową.

0

OK, doprecyzowuję zatem. Druga funkcja szuka dokładnie w tym samym tekście daty powiązanej z numerem błędu wyszukanego w pierwszej funkcji. Założmy, że odpowiednia data jest zawsze 20 znaków przed wstapieniem numeru błędu i zawiera 10 znaków. Finalnie w drugiej kolumnie chciałbym zobaczyć dla każdego wiersza z błędem date jego wystąpienia. Widzę, że cross apply nie jest tu rozwiązaniem bo łączy wszystko ze wszystkim. Więc teraz idę albo w kierunku - funkcja tableraryczna, która zwraca dwie kolumny albo złączenie wyników obu selectów z dwoma odzielnymi funkcjami.

Wszelkie wskazówi mile widziane:)

Pozdrawiam,
Arek

0

Podaj przykładowy string w którym szukasz zamień to czego nie możesz pokazać ważne żeby długości się zgadzały

0

String jest np. taki:
CXCSDSSDSD 50 6/27/2018 2:22:52 PM 160263 10.39.53 2308937_578498 XSDS DSD dsdscsdds dsds 0 49 6/27/2018 12:14:57 PM 160236 31.03.36 2308937_578498 Mdsdsds dsds ssdsr or 48 6/26/2018 10:28:37 AM 160059 31.13.02 2 dsds sds

i chce finalnie uzyskać w dwóch oddzielnych kolumnach:
Error Time
10.39.53 6/27/2018 2:22:52 PM
31.03.36 6/27/2018 12:14:57 PM
31.13.02 6/26/2018 10:28:37 AM

Dziękuję za pomoc.
A.

0

Data jest około 30 znaków ponieważ jej zapis bez zer wiadących sprawia, ze długość samej daty może być od 8 (1/1/2019) do 10 (12/12/2018) znaków, jak i godzina też nie ma stałej długości, można to obejść i "wyłuskać":

ALTER  FUNCTION [dbo].[parseTicketTextToRows]
                (@text VARCHAR(500))
RETURNS @RtnValue TABLE
(
    error VARCHAR(8) NOT NULL
    ,[time] VARCHAR(30) NOT NULL
)
AS
BEGIN
declare @i as integer 
declare @error varchar(100)
declare @time varchar(300)

set @i = patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text)

while  @i>0
BEGIN 
    SET @Error = SUBSTRING(@text,@i,8)
    set @time = substring(@text,@i-30,30)
    set @time = substring(@time,case when charindex(' ',@time)>8 then 1 else charindex(' ',@time)+1 end,patindex('% [pa]m%',@time)-case when charindex(' ',@time)>8 then 0 else charindex(' ',@time) end+3)
    INSERT INTO @RtnValue VALUES (@error,@time)
    SET @text = STUFF(@text, patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text), 8, '')
    set @i = patindex('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%',@text)
END

RETURN
END

GO

Celowo wprowadziłem zmienne, aby było czytelniej do analizy, wykorzystanie:

SELECT 
    ticket
    , f.error
    , f.[time] 
FROM 
    ticket 
    CROSS apply [dbo].[parseTicketTextToRows](ticket.text) f

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0