Как разделить строку с помощью разделителя char с помощью T-SQL?
у меня есть эта длинная строка в одном из столбцов таблицы. Я хочу получить только конкретную информацию:- Моя структура таблицы: -
Col1 = '123'
Col2 = 'AAAAA'
Col3 = 'Clent ID = 4356hy|Client Name = B B BOB|Client Phone = 667-444-2626|Client Fax = 666-666-0151|Info = INF8888877 -MAC333330554/444400800'
моя инструкция select: -
Select col1, col2, col3 from Table01
но в Col3 мне просто нужно значение "имя клиента, которое является "B B BOB".
В Col3 -
разделитель столбцов - ' / ' pipe char (например. 'Client ID = 4356hy')
разделитель ключевого значения ' = ' равен знаку с одним белым пространство (начальные и конечные).
пожалуйста, помогите.
4 ответов
для ваших конкретных данных, вы можете использовать
Select col1, col2, LTRIM(RTRIM(SUBSTRING(
STUFF(col3, CHARINDEX('|', col3,
PATINDEX('%|Client Name =%', col3) + 14), 1000, ''),
PATINDEX('%|Client Name =%', col3) + 14, 1000))) col3
from Table01
редактировать-charindex против patindex
тест
select col3='Clent ID = 4356hy|Client Name = B B BOB|Client Phone = 667-444-2626|Client Fax = 666-666-0151|Info = INF8888877 -MAC333330554/444400800'
into t1m
from master..spt_values a
cross join master..spt_values b
where a.number < 100
-- (711704 row(s) affected)
set statistics time on
dbcc dropcleanbuffers
dbcc freeproccache
select a=CHARINDEX('|Client Name =', col3) into #tmp1 from t1m
drop table #tmp1
dbcc dropcleanbuffers
dbcc freeproccache
select a=PATINDEX('%|Client Name =%', col3) into #tmp2 from t1m
drop table #tmp2
set statistics time off
тайминги
CHARINDEX:
SQL Server Execution Times (1):
CPU time = 5656 ms, elapsed time = 6418 ms.
SQL Server Execution Times (2):
CPU time = 5813 ms, elapsed time = 6114 ms.
SQL Server Execution Times (3):
CPU time = 5672 ms, elapsed time = 6108 ms.
PATINDEX:
SQL Server Execution Times (1):
CPU time = 5906 ms, elapsed time = 6296 ms.
SQL Server Execution Times (2):
CPU time = 5860 ms, elapsed time = 6404 ms.
SQL Server Execution Times (3):
CPU time = 6109 ms, elapsed time = 6301 ms.
вывод
тайминги для CharIndex и PatIndex для вызовов 700k находятся в пределах 3,5% друг от друга, поэтому я не думаю, что это будет иметь значение в зависимости от того, что используется. Я использую их взаимозаменяемо, когда оба могут работать.
вам нужна функция разделения:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create Function [dbo].[udf_Split]
(
@DelimitedList nvarchar(max)
, @Delimiter nvarchar(2) = ','
)
RETURNS TABLE
AS
RETURN
(
With CorrectedList As
(
Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
+ @DelimitedList
+ Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
As List
, Len(@Delimiter) As DelimiterLen
)
, Numbers As
(
Select TOP( Coalesce(DataLength(@DelimitedList)/2,0) ) Row_Number() Over ( Order By c1.object_id ) As Value
From sys.columns As c1
Cross Join sys.columns As c2
)
Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
, Substring (
CL.List
, CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen
, CharIndex(@Delimiter, CL.list, N.Value + 1)
- ( CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen )
) As Value
From CorrectedList As CL
Cross Join Numbers As N
Where N.Value <= DataLength(CL.List) / 2
And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
)
С помощью функции split вы затем используете Cross Apply для получения данных:
Select T.Col1, T.Col2
, Substring( Z.Value, 1, Charindex(' = ', Z.Value) - 1 ) As AttributeName
, Substring( Z.Value, Charindex(' = ', Z.Value) + 1, Len(Z.Value) ) As Value
From Table01 As T
Cross Apply dbo.udf_Split( T.Col3, '|' ) As Z
вам просто нужно сделать SUBSTR в строке в col3....
Select col1, col2, REPLACE(substr(col3, instr(col3, 'Client Name'),
(instr(col3, '|', instr(col3, 'Client Name') -
instr(col3, 'Client Name'))
),
'Client Name = ',
'')
from Table01
и да, это плохой дизайн БД по причинам, указанным в исходном выпуске
Это ужасно, но вы можете попробовать использовать
select
SUBSTRING(Table1.Col1,0,PATINDEX('%|%=',Table1.Col1)) as myString
from
Table1
этот код, вероятно,не на 100% прав. необходимо настроить