Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Распарсить строку  [new]
jango77
Member

Откуда:
Сообщений: 41
Добрый день
Помогите пожалуйста распарсить строку такого типа:

{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}

И каждый элемент записать как отдельную запись. В строке разное количество элементов


Сейчас запрос возвращает
ID; PRODUCT_IDS
15; {i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}

Нужно получить

ID; PRODUCT_IDS
15; 3947
15; 4343
15; 4345
15; 4644
15; 4627
13 дек 19, 15:25    [22039816]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20492
Убрать обрамляющие скобки, финишную точку с запятой, 'i:', а остаток STRING_SPLIT-нуть... например.

Сообщение было отредактировано: 13 дек 19, 15:30
13 дек 19, 15:30    [22039838]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1357
jango77,

версия сервера у вас какая?
select @@VERSION
13 дек 19, 15:30    [22039841]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
barry
Member

Откуда: Kharkov
Сообщений: 478
jango77,

STRING_SPLIT
13 дек 19, 16:03    [22039903]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1357
если порядок не задается нечетными элементами то так

declare @v varchar(max) = '{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}'
set @v = replace(replace(@v, '{', ''), '}', '');
with x as (
    select row_number() over (order by 1/0) % 2 as [rn], * from string_split(@v, ';')
),
y as (
    select 
    row_number() over (order by 1/0) as [rn2],
    v.[value]
    from x 
          cross apply string_split(x.value, ':') v
    where rn = 0
)
select row_number() over (order by 1/0) as [rn],
       [value]
from y
where [rn2] % 2 = 0
13 дек 19, 16:10    [22039922]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
jango77
Member

Откуда:
Сообщений: 41
felix_ff
jango77,

версия сервера у вас какая?
select @@VERSION



Microsoft SQL Server 2017 (RTM-GDR) (KB4505224) - 14.0.2027.2 (X64) Jun 15 2019 00:26:19 Copyright (C) 2017 (64-bit)
13 дек 19, 16:19    [22039932]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Karbafos
Member

Откуда:
Сообщений: 464
felix_ff
если порядок не задается нечетными элементами то так

declare @v varchar(max) = '{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}'
set @v = replace(replace(@v, '{', ''), '}', '');
with x as (
    select row_number() over (order by 1/0) % 2 as [rn], * from string_split(@v, ';')
),
y as (
    select 
    row_number() over (order by 1/0) as [rn2],
    v.[value]
    from x 
          cross apply string_split(x.value, ':') v
    where rn = 0
)
select row_number() over (order by 1/0) as [rn],
       [value]
from y
where [rn2] % 2 = 0


Это сериализованный массив интов пехапешным сериализатором.

Нечетные элементы это индексы массива в виде тип:значение, четные -- значения вида тип:значение для интов, а в случае строк значение будет так s:3:"bfg"
ЗЫ: И вообще полная строка должна выглядеть вот так a:5:{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}
13 дек 19, 16:54    [22039978]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
jango77
Member

Откуда:
Сообщений: 41
Karbafos
felix_ff
если порядок не задается нечетными элементами то так


ЗЫ: И вообще полная строка должна выглядеть вот так a:5:{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}


так и есть. От a:5: удалось избавиться
13 дек 19, 17:03    [22039988]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
jango77
Member

Откуда:
Сообщений: 41
felix_ff
если порядок не задается нечетными элементами то так

declare @v varchar(max) = '{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}'
set @v = replace(replace(@v, '{', ''), '}', '');
with x as (
    select row_number() over (order by 1/0) % 2 as [rn], * from string_split(@v, ';')
),
y as (
    select 
    row_number() over (order by 1/0) as [rn2],
    v.[value]
    from x 
          cross apply string_split(x.value, ':') v
    where rn = 0
)
select row_number() over (order by 1/0) as [rn],
       [value]
from y
where [rn2] % 2 = 0


Подскажите, пожалуйста, как этот синтаксис увязать с тем, что нужно распарсить со строки эти PRODUCT_IDS для каждого ID, чтобы селектом получить
ID; PRODUCT_IDS
15; 3947
15; 4343
15; 4345
15; 4644
15; 4627
13 дек 19, 17:31    [22040028]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7671
jango77,

парсеры хорошо пишутся на C# в виде табличных CLR функций. Поищите в инете.
13 дек 19, 17:47    [22040071]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Shakill
Member

Откуда: мск
Сообщений: 1880
jango77,


declare @t table(id int, product_ids nvarchar(100))

insert @t (id, product_ids) values
(15, '{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}'),
(16, '{i:0;i:232;i:1;i:5345;i:2;i:34534;i:3;i:1212;i:4;i:5555;}')

select 
	t.id, 
	product_ids = z.[value]
from @t as t
cross apply(values(replace(replace(replace(replace(t.product_ids, 'i:', ''), ';}', ']'), ';', ','), '{', '['))) as tt(jsn)
cross apply openjson(tt.jsn) as z
where z.[key] % 2 = 1
13 дек 19, 17:56    [22040083]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
jango77
Member

Откуда:
Сообщений: 41
Владислав Колосов
jango77,

парсеры хорошо пишутся на C# в виде табличных CLR функций. Поищите в инете.


Хотелось бы решить всю задачу через T-SQL (пишем импорт с базы битрикса)
чтобы вести разработку через одну точку администрирования импортов

Спасибо за предложенный вариант
13 дек 19, 18:02    [22040096]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
jango77
Member

Откуда:
Сообщений: 41
Shakill
jango77,


declare @t table(id int, product_ids nvarchar(100))

insert @t (id, product_ids) values
(15, '{i:0;i:3947;i:1;i:4343;i:2;i:4345;i:3;i:4644;i:4;i:4627;}'),
(16, '{i:0;i:232;i:1;i:5345;i:2;i:34534;i:3;i:1212;i:4;i:5555;}')

select 
	t.id, 
	product_ids = z.[value]
from @t as t
cross apply(values(replace(replace(replace(replace(t.product_ids, 'i:', ''), ';}', ']'), ';', ','), '{', '['))) as tt(jsn)
cross apply openjson(tt.jsn) as z
where z.[key] % 2 = 1


Shakill, Спасибо Вам! Работает так как нужно по задаче
13 дек 19, 18:08    [22040103]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить