Извлечение текста из строки с разделителями в другую строку с разделителями TSQL

#sql-server #tsql

#sql-сервер #tsql

Вопрос:

У меня есть эта строка, например Green/1051;Brown/1258;Red/1110;Yellow /1024;Red/1147;

И я хотел бы иметь возможность получить следующую строку из этого 1051;1258;1110;1024;1147;

Я пробовал несколько решений, но они, как правило, обслуживают одну «часть» строки. Если это невозможно, я могу отформатировать это на стороне c #, однако было бы неплохо иметь возможность делать это в моей хранимой процедуре.

Спасибо

РЕДАКТИРОВАТЬ: К сожалению, это сторонний набор данных, поэтому я отформатировал эти данные с помощью C #. Из приведенных ниже ответов я согласен с тем, что SQL не предназначен для извлечения и анализа того, что мне нужно, его просто было бы проще поддерживать.

Комментарии:

1. SQL, язык, не предназначен для синтаксического анализа строк. Почему вы пытаетесь проанализировать эту строку в SQL в первую очередь? Вы не можете воспользоваться индексами или запросами. Если вы использовали формат, уже поддерживаемый SQL Server, например XML или JSON, вы могли бы, по крайней мере, запросить данные

2. Я пробовал несколько решений —> Пожалуйста, добавьте свой код

3. Что вы пытаетесь сделать в первую очередь? Если вам нужны части этих данных, зачем хранить их в виде строки, подобной этой? И почему сервер должен ее анализировать? Вы хотите использовать результаты в других запросах? Ответ имеет большое значение. Если вы хотите использовать результаты в более крупном запросе, вам, вероятно, следует рассмотреть возможность использования правильного дизайна таблицы, например, с разреженными столбцами или отдельной связанной таблицей. Другим вариантом может быть замена / и ; на " » и ' сделать его похожим на JSON, чтобы вы могли использовать OPENJSON для извлечения значений в качестве результирующего набора.

4. @PanagiotisKanavos Это сторонняя таблица с данными, не введенными моим me. Поверьте мне, я знаю, что это очень плохой способ хранения этих данных. Если это невозможно, я просто отформатирую это на стороне C #.

5. @JackWaters вы еще не объяснили, чего хотите. Вы хотите использовать результаты в запросе или нет? Если нет , зачем беспокоиться о синтаксическом анализе в базе данных? Какую версию SQL Server вы используете?

Ответ №1:

Я предполагаю, что причина, по которой данные должны быть проанализированы на сервере, заключается в их использовании в большем запросе. В противном случае нет причин анализировать его на сервере. Было бы намного проще сделать это на C #, например, с помощью регулярного выражения.

Не зная, какой это SQL Server, я просто предположу, что это 2016 или более поздняя версия, потому что это позволяет нам преобразовать строку в значение JSON, заменив на ":" и ; на "," . Аналогичный метод можно использовать в более старых версиях для преобразования строки в XML.

Предполагая, что эта простая таблица :

 declare @table table (id int identity primary key,col varchar(max))

insert into @table (col)
values ('Green/1051;Brown/1258;Red/1110;Yellow /1024;Red/1147;')
  

Мы можем использовать STUFF(col,len(col),1,'') для удаления конечной точки с запятой. Этот запрос :

 select stuff(col,len(col),1,'')
from @table
  

Дает

 Green/1051;Brown/1258;Red/1110;Yellow /1024;Red/1147
  

Замена / и ; с

 select replace(replace(stuff(col,len(col),1,''),'/','":"'),';','","')
from @table
  

Дает :

 Green":"1051","Brown":"1258","Red":"1110","Yellow ":"1024","Red":"1147
  

Теперь нам просто нужно заполнить строку JSON, окружив это значение {" символом и "} .

Как только мы это сделаем, мы можем использовать OPENJSON :

 select *
from @table 
    cross apply openjson('{"'   replace(replace(stuff(col,len(col),1,''),'/','":"'),';','","')   '"}')
  

Это вернет id col столбцы , из исходной таблицы и key , value и type столбцы из OPENJSON :

 select id,[key],value
from @table 
    cross apply openjson('{"'   
replace(replace(stuff(col,len(col),1,''),'/','":"'),';','","')   '"}') x
  

Вернет :

 id  key     value
1   Green   1051
1   Brown   1258
1   Red     1110
1   Yellow  1024
1   Red     1147
  

Мы можем объединить эти результаты с другой таблицей. Допустим, эти числа являются идентификаторами элементов, и у нас есть таблица инвентаризации с запасами для каждого из них :

 declare @inventory table (colorid int,amount int)

insert into @inventory (colorid,amount)
values
(1051,5),
(1258,10),
(1110,24),
(1024,2),
(1147,22)
  

Количество каких элементов превышает 20?

 select id, [key],colorid,amount
from @table 
    cross apply openjson('{"'   replace(replace(stuff(col,len(col),1,''),'/','":"'),';','","')   '"}') x
inner join @inventory i on i.colorid=x.value
where amount>20
  

Результат :

 id  key colorid amount
1   Red 1110    24
1   Red 1147    22
  

Комментарии:

1. Спасибо за это. И да, это SQL 2016

Ответ №2:

Найдите DelimitedSplit8K. Это позволит вам преобразовать строку в несколько строк, разделяющихся на ;

Затем вы можете использовать STUFF ..FOR XML для восстановления строки

В качестве альтернативы, если вы знаете, что вам всегда будут нужны ВСЕ числа и точки с запятой, и НИ ОДНА из букв и пробелов, которые вы могли бы использовать

 REPLACE(REPLACE(instring,[A-Z],''),' ','')
  

Комментарии:

1. Это не полезный ответ. DelimitedSplit8K это просто название, которое Аарон Бертран дал одному из методов, которые он тестировал. Указание кому-либо просто искать статьи не очень полезно. Кроме того, вместо многократного разделения можно использовать метод XML для преобразования строки в правильную строку XML с атрибутами, которые можно запрашивать

2. Что такое столбец [A-Z] ? Если подразумевается, что это строка REPLACE , не поддерживает выражения шаблонов.

3. @PanagiotisKanavos на самом деле это имя Джефф Моден дал функции , которую он разработал.

4. @Larnu Я знаю, но я не хочу искать это в Google. Ответчик должен был это сделать.

5. С этим я согласен @PanagiotisKanavos