Разделить записи в столбце, разделенном разделителем

У меня есть проблема, с которой мне нужна помощь. У меня есть столбец с набором строк, которые разделены "." (Пример ниже) У меня есть запрос, чтобы разделить его с помощью подстроки и charindex, проблема в том, что второй разделитель не всегда имеет одинаковую длину, поэтому, когда я это делаю, он не разделяется правильно.

Column A
100.11111.12.16
101.36333
101.REMOTE.01
200.ACTIVE

Мне нужно, чтобы вышеуказанные данные были разбиты на 3 столбца.

Column A           Column B      Column C     Column D
100.11111.12.16    100           11111          12.16
101.36333          101           36333  
101.REMOTE.01      101           REMOTE          01
200.ACTIVE         200           ACTIVE

Как вы можете видеть, второй разделитель не всегда попадает в одну и ту же позицию всегда. Первое всегда после 3, поэтому я могу разделить его, но во втором случае возникают проблемы с разделением, потому что я не могу определить точное местоположение.

4 ответа

Решение

Для этого решения необходимо знать о функции ISNULL. Ссылки на функции SUBSTRING, NULLIF, CHARINDEX были даны ранее уважаемым @Pரதீப். Функция LEN говорит сама за себя.

SELECT a [Column A],
  SUBSTRING(a, 1, ISNULL(p1 - 1, LEN(a))) [Column B],
  SUBSTRING(a, p1 + 1, ISNULL(p2, LEN(a) + 1) - p1 - 1) [Column C],
  SUBSTRING(a, p2 + 1, LEN(a) - p2) [Column D]
FROM(VALUES('100.11111.12.16'),
           ('101.36333'),
           ('101.REMOTE.01'),
           ('200.ACTIVE'),
           ('42170')) a(a)
CROSS APPLY(VALUES(NULLIF(CHARINDEX('.', a), 0))) b(p1)
CROSS APPLY(VALUES(NULLIF(CHARINDEX('.', a, p1 + 1), 0))) c(p2)
CROSS APPLY(VALUES(NULLIF(CHARINDEX('.', a, p2 + 1), 0))) d(p3);

Проверьте это на http://rextester.com/TOKRH13046.

Вот один из способов использования строковых функций

SELECT [Column A] = t.string, 
       [Column B] = LEFT(t.string, Charindex('.', t.string) - 1), 
       [Column C] = Reverse(Parsename(Reverse(cs.string), 1)), 
       [Column D] = Stuff(cs.string, 1, NULLIF(fpos, 0), '') 
FROM   Yourtable t 
       CROSS apply(VALUES (Substring(string, Charindex('.', string) + 1, Len(string))))cs(string) 
       CROSS apply(VALUES (Charindex('.', cs.string))) p (fpos) 

Ссылки MSDN:

Еще один вариант использования небольшого XML в сочетании с CROSS APPLY

пример

Declare @YourTable Table ([Column A] varchar(50))
Insert Into @YourTable Values 
 ('100.11111.12.16')
,('101.36333')
,('101.REMOTE.01')
,('200.ACTIVE')

Select A.* 
      ,[Column B] = B.Pos1
      ,[Column C] = B.Pos2
      ,[Column D] = substring(concat('.'+B.Pos3,'.'+B.Pos4),2,50)
 From  @YourTable A
 Cross Apply (
                Select Pos1 = xDim.value('/x[1]','varchar(max)')
                      ,Pos2 = xDim.value('/x[2]','varchar(max)')
                      ,Pos3 = xDim.value('/x[3]','varchar(max)')
                      ,Pos4 = xDim.value('/x[4]','varchar(max)')
                From  (Select Cast('<x>' + replace(A.[Column A],'.','</x><x>')+'</x>' as xml) as xDim) as X
             ) B

Возвращает

Если максимальное количество точек равно 3, тогда parsename может выполнить всю работу:

select columnA,
       parsename(reverse(columnA),1) columnB,
       parsename(reverse(columnA),2) columnC,
       parsename(reverse(columnA),3) + isnull('.'+parsename(reverse(columnA),4),'')  columnD
from table
Другие вопросы по тегам