#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