Разделите разными символами sql

#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.