#sql #sql-server #split #delimiter
Вопрос:
Итак, у меня есть столбец, который содержит несколько разных строк. Если строка содержит_, она должна быть разделена на этот символ. Для других, которые я использую, я бы использовал отдельное правило, например: Если он начинается с 4FH, GWO, CTW и не имеет_, то он должен разделяться после 3 символов. Если он начинается с 4 и не имеет _.. и т. Д..
Example
|Source |
|EC_HKT |
|4FHHTK |
|ABC_GJE |
|4SHARED |
|ETK_ETK-40|
etc..
Чего я в результате хочу, так это
|Source|Instance|
|EC |HKT |
|4FH |HTK |
|ABC |GJE |
|4 |SHARED |
|ETK |40 |
Для начала я сначала попробовал
SELECT
LEFT(lr.Source, CHARINDEX('_',lr.Source)) AS Source,
RIGHT(lr.Source, LEN(lr.Source) - CHARINDEX('_', lr.Source)) AS Interface,
Но это сработало бы только в том случае, если бы все результаты имели _ . Какие-нибудь советы или идеи? Будет ЛИ СЛУЧАЙ, КОГДА ЭТО СРАБОТАЕТ?
Комментарии:
1. Пожалуйста, объясните свои правила разделения строки. Это не очевидно.
2. Я добавил это туда.
3. Это произвольные тексты и правила, для этого вам в значительной степени понадобится сопоставление, поэтому в значительной степени разделение выполняется вручную. Вы можете начать создавать указанное сопоставление с помощью простых правил, но в конце концов это не приведет к простому преобразованию. (например, 10 SHARED сопоставляется с 10 и СОВМЕСТНО ИСПОЛЬЗУЕТСЯ или 1 и 0 SHARED? Сопоставляется ли ABC_ABC-GJE с ABC и GJE или ABC и ABC-GJE? Почему?
4. Это слишком произвольно, чтобы применять к этому какую-либо общую логику. Я бы создал функцию, которая реализует ваши правила и вычисляет позицию символа для разделения, затем вы можете использовать ее, чтобы разделить строку пополам.
5. Если он начинается с 4 ч, он также начинается с 4, так как вы знаете, что нужно разделиться после 4 или после 4 ч?
Ответ №1:
Это требует небольшого творческого подхода и, несомненно, большей работы, чем то, что я сделал здесь, однако это дает вам по крайней мере один шаблон для работы и улучшения по мере необходимости.
В приведенном ниже примере используется простая функция для применения основных правил из ваших выборочных данных для получения точки разделения строки, а также для дополнительного удаления символов и удаления исходной части, если она также существует в части экземпляра.
Если совпадает более одного «правила», оно использует правило с большим количеством совпадающих символов.
Функция:
create or alter function splitpos(@string varchar(50))
returns table as
return
(
with map as (
select * from (values ('4FH'),('GWO'),('CTW'),('4'))m(v)
)
select IsNull(NullIf(CharIndex('_',@string),0)-1,Max(Len(m.v))) pos
from map m
where @string like m.v '%'
)
Запрос:
select l.v source, Replace(Replace(Replace(Stuff(source,1,pos,''),'_',''),'-',''),l.v,'') instance
from t
cross apply dbo.splitpos(t.source)
cross apply (values(Left(source,pos)))l(v)
Ответ №2:
Чтобы разделить по разным правилам, используйте CASE
выражение. (W3Schools)
SELECT CASE
WHEN lr.Source LIKE '4FH%' AND CHARINDEX('_', lr.Source) = 0
THEN LEFT(lr.Source, 3)
...
END as Source
Если тезисы являются отдельными столбцами, то для каждого столбца вам потребуется инструкция case.
Комментарии:
1. @jarlh спасибо, я изменил его, чтобы он соответствовал Microsoft и не был таким гребаным
2. Оператор case — это конструкция хранимой процедуры для условного выполнения кода. Выражение case возвращает значение и может использоваться практически везде, где вам нужно значение. Все в соответствии со стандартом ANSI/ISO SQL.