разбить строку на несколько полей в каждом вхождении разделителя - PullRequest
0 голосов
/ 20 апреля 2020

Мне нужно, чтобы поле DISPLAYVALUE разбивалось на несколько полей при каждом появлении '-'.

Например,

DISPLAYVALUE
111111-LTL-HOU-SALES-EMP-DM

становится:

Main Account    BusinessUnit    Department  CostCenter  AssetType   Classification
111111              LTL            HOU         SALES       EMP            DM

Я использовал комбинацию подстрок и charindex, но 6-ти разное размещение меня немного смутило. Есть ли более простое решение? спасибо

Ответы [ 2 ]

0 голосов
/ 20 апреля 2020

Вы можете разделить исходную строку на 2 меньшие части, которые затем могут быть переданы в функцию parsename, которая может быть полезна для этого. Нам нужно сделать это, потому что parsename может анализировать только до 4 частей, разделенных символом .. Таким образом, вы можете сделать

with your_table as (select '111111-LTL-HOU-SALES-EMP-DM' as txt)

select parsename(replace(p1,'-','.'),2),
       parsename(replace(p1,'-','.'),1),
       parsename(replace(p2,'-','.'),4),
       parsename(replace(p2,'-','.'),3),
       parsename(replace(p2,'-','.'),2),
       parsename(replace(p2,'-','.'),1)
from your_table t1
cross apply (select charindex( '-', txt) as i1) t2 --locate 1st occurrence of -
cross apply (select charindex( '-', txt, (i1 + 1)) as i2 ) t3 --locate 2nd occurrence of -
cross apply (select left( txt,i2-1) as p1) t4 --get all before 2nd occurrence of -
cross apply (select replace(txt,left( txt,i2),'') as p2) t5; --get all after 2nd occurrence of -

Я использую cross apply, потому что, даже за счет многословия, это делает логику c достижения двух меньших частей более читабельной.

Убедитесь, что отдельные анализируемые части не длиннее 256 символов каждая, и у вас нет . символов в строке, в противном случае это не сработает, и вам может быть лучше использовать подход, основанный на XML.

DEMO

0 голосов
/ 20 апреля 2020

Вы можете использовать рекурсивный CTE:

with cte as (
      select convert(varchar(max), '111111-LTL-HOU-SALES-EMP-DM') as rest, convert(varchar(max), NULL) as val, 0 as lev
      union all
      select stuff(rest, 1, charindex('-', rest + '-'), ''), left(rest, charindex('-', rest + '-') - 1), lev + 1
      from cte
      where rest > ''
     )
select max(case when lev = 1 then val end) as mainaccount,
       max(case when lev = 2 then val end) as BusinessUnit,
       max(case when lev = 3 then val end) as department,
       max(case when lev = 4 then val end) as CostCenter,
       max(case when lev = 5 then val end) as AssetType,
       max(case when lev = 6 then val end) as Classification
from cte;

Здесь - это db <> скрипка.

Примечание: Если строка является столбцом в таблице , то вам нужно будет агрегировать по первичному ключу.

...