SQL Server 2012 将字符串按分隔符分成三列
SQL Server 2012 divide string into three columns by deliminter
用多个定界符分隔下面的字符串时遇到问题
示例数据
column1
row1 'ABC>DEF>GHI'
row2 'ABC>DEF>GHI'
row3 'ABC>DEF'
row4 'ABC>DEF'
row5 'ABC>DEF>GHI'
目标
col1 col2 col3
row1 'ABC' 'DEF' 'GHI'
row2 'ABC' 'DEF' 'GHI'
row3 'ABC' 'DEF'
row4 'ABC' 'DEF'
row5 'ABC' 'DEF' 'GHI'
我想将这一行分成 3 列,每列前后 >
我已经管理了这 2 个在第一个定界符之前和最后一个定界符之后捕获的 case 语句,但我一直在两个定界符之间捕获。
CASE
WHEN Indicator LIKE '%>%'
THEN LEFT (column1, Charindex('>' , column1) - 1)
ELSE col1
END as col1
CASE
WHEN Indicator LIKE '%>%'
THEN RIGHT (column1, Charindex('>' , Reverse(column1)) - 1)
END as col3
如有任何帮助,我们将不胜感激
谢谢
使用 Parsename
函数技巧来做到这一点。
SELECT Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 1)) col1,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 2)) col2,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 3)) col3
FROM tablename
演示
create table #test( column1 varchar(500))
insert #test values
('ABC > DEF > GHI'),
('ABC > DEF > GHI'),
('ABC > DEF '),
('ABC > DEF '),
('ABC > DEF > GHI')
SELECT Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 1)) col1,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 2)) col2,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 3)) col3
FROM #test
结果:
col1 col2 col3
---- ---- ----
ABC DEF GHI
ABC DEF GHI
ABC DEF NULL
ABC DEF NULL
ABC DEF GHI
您不应在单个字段中存储定界字符串,因为这取决于您。假设您别无选择,只能解析定界字符串,这是我经常使用的解析函数:
/********************************************************************************************
Create Parse Function
********************************************************************************************/
CREATE FUNCTION dbo.FN_PARSE(@chunk VARCHAR(4000), @delimiter CHAR(1), @index INT )
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE
@curIndex INT = 0,
@pos INT = 1,
@prevPos INT = 0,
@result VARCHAR(1000)
WHILE @pos > 0
BEGIN
SET @pos = CHARINDEX(@delimiter, @chunk, @prevPos);
IF(@pos > 0)
BEGIN -- Characters between position and previous position
SET @result = SUBSTRING(@chunk, @prevPos, @pos-@prevPos)
END
ELSE
BEGIN -- Last Delim
SET @result = SUBSTRING(@chunk, @prevPos, LEN(@chunk))
END
IF(@index = @curIndex)
BEGIN
RETURN @result
END
SET @prevPos = @pos + 1
SET @curIndex = @curIndex + 1;
END
RETURN '' -- Else Empty
END
用法很简单,用三个参数调用函数,字段、分隔符和索引return。
SELECT dbo.FN_PARSE(column1,'>', 0) AS Col1
,dbo.FN_PARSE(column1,'>', 1) AS Col2
,dbo.FN_PARSE(column1,'>', 2) AS Col3
FROM YourTable
请注意索引值从 0
开始。与 PARSENAME()
不同,这将处理超过 4 个部分,但这也可能效率较低。
用多个定界符分隔下面的字符串时遇到问题
示例数据
column1
row1 'ABC>DEF>GHI'
row2 'ABC>DEF>GHI'
row3 'ABC>DEF'
row4 'ABC>DEF'
row5 'ABC>DEF>GHI'
目标
col1 col2 col3
row1 'ABC' 'DEF' 'GHI'
row2 'ABC' 'DEF' 'GHI'
row3 'ABC' 'DEF'
row4 'ABC' 'DEF'
row5 'ABC' 'DEF' 'GHI'
我想将这一行分成 3 列,每列前后 >
我已经管理了这 2 个在第一个定界符之前和最后一个定界符之后捕获的 case 语句,但我一直在两个定界符之间捕获。
CASE
WHEN Indicator LIKE '%>%'
THEN LEFT (column1, Charindex('>' , column1) - 1)
ELSE col1
END as col1
CASE
WHEN Indicator LIKE '%>%'
THEN RIGHT (column1, Charindex('>' , Reverse(column1)) - 1)
END as col3
如有任何帮助,我们将不胜感激
谢谢
使用 Parsename
函数技巧来做到这一点。
SELECT Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 1)) col1,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 2)) col2,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 3)) col3
FROM tablename
演示
create table #test( column1 varchar(500))
insert #test values
('ABC > DEF > GHI'),
('ABC > DEF > GHI'),
('ABC > DEF '),
('ABC > DEF '),
('ABC > DEF > GHI')
SELECT Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 1)) col1,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 2)) col2,
Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 3)) col3
FROM #test
结果:
col1 col2 col3
---- ---- ----
ABC DEF GHI
ABC DEF GHI
ABC DEF NULL
ABC DEF NULL
ABC DEF GHI
您不应在单个字段中存储定界字符串,因为这取决于您。假设您别无选择,只能解析定界字符串,这是我经常使用的解析函数:
/********************************************************************************************
Create Parse Function
********************************************************************************************/
CREATE FUNCTION dbo.FN_PARSE(@chunk VARCHAR(4000), @delimiter CHAR(1), @index INT )
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE
@curIndex INT = 0,
@pos INT = 1,
@prevPos INT = 0,
@result VARCHAR(1000)
WHILE @pos > 0
BEGIN
SET @pos = CHARINDEX(@delimiter, @chunk, @prevPos);
IF(@pos > 0)
BEGIN -- Characters between position and previous position
SET @result = SUBSTRING(@chunk, @prevPos, @pos-@prevPos)
END
ELSE
BEGIN -- Last Delim
SET @result = SUBSTRING(@chunk, @prevPos, LEN(@chunk))
END
IF(@index = @curIndex)
BEGIN
RETURN @result
END
SET @prevPos = @pos + 1
SET @curIndex = @curIndex + 1;
END
RETURN '' -- Else Empty
END
用法很简单,用三个参数调用函数,字段、分隔符和索引return。
SELECT dbo.FN_PARSE(column1,'>', 0) AS Col1
,dbo.FN_PARSE(column1,'>', 1) AS Col2
,dbo.FN_PARSE(column1,'>', 2) AS Col3
FROM YourTable
请注意索引值从 0
开始。与 PARSENAME()
不同,这将处理超过 4 个部分,但这也可能效率较低。