T-SQL在分隔符上拆分列
我有一个包含三组数据的列,数据以正斜杠分隔,如下所示T-SQL在分隔符上拆分列,sql,sql-server,tsql,sql-server-2012,Sql,Sql Server,Tsql,Sql Server 2012,我有一个包含三组数据的列,数据以正斜杠分隔,如下所示 AB/1234/10 列在每一行中的格式始终相同,有2个字符、一个斜杠、一些字符数、一个斜杠,然后还有2个字符。我需要把这一栏分成三栏。所以上面的例子变成了 Column1 Column2 Column3 AB 1234 10 我不太清楚该怎么办。我一直在使用selectsubstring,但这并不能满足我的需要 select SUBSTRING(MyColumn, 1, CHARINDEX('/', MyColumn,
AB/1234/10
列在每一行中的格式始终相同,有2个字符、一个斜杠、一些字符数、一个斜杠,然后还有2个字符。我需要把这一栏分成三栏。所以上面的例子变成了
Column1 Column2 Column3
AB 1234 10
我不太清楚该怎么办。我一直在使用selectsubstring
,但这并不能满足我的需要
select SUBSTRING(MyColumn, 1, CHARINDEX('/', MyColumn, 1)-1)
FROM MyTable
将返回AB
,这很好。但我无法集中精力思考如何抓住中间和结尾部分。我以为
select SUBSTRING(MyColumn, 4, CHARINDEX('/', MyColumn, 4))
FROM MyTable
可以抓住中间部分,但它返回1234/10
我希望我的问题是明确的,我将感谢任何建议指向正确的方向,谢谢你 您可以使用固定偏移量,因为您定义了字符串始终以两个字符开头,以两个字符结尾
DECLARE @str VARCHAR(100) = 'AB/1234/10'
SELECT LEFT(@str, CHARINDEX('/', @str) - 1) AS Column1
, SUBSTRING(@str, CHARINDEX('/', @str) + 1, CHARINDEX('/', SUBSTRING(@str, CHARINDEX('/', @str) + 1, LEN(@str))) - 1) AS Column2
, RIGHT(@str, CHARINDEX('/', REVERSE(@str)) - 1) AS Column3
下面是一个完整的工作示例:
DECLARE @tmp TABLE (
Merged nvarchar(max)
)
INSERT INTO @tmp SELECT N'AB/1234/10'
INSERT INTO @tmp SELECT N'AB/ANYNUMBEROF-CHARACTERS/10'
SELECT
LEFT(Merged,2) AS Column1,
SUBSTRING(Merged,4,LEN(Merged)-6) AS Column2,
RIGHT(Merged,2) AS Column3
FROM @tmp
我们减去字符串的长度减去一个常数(6=左两个字符,右两个字符,两个斜线),从中间提取可变长度部分
结果:
Column1 Column2 Column3
AB 1234 10
AB ANYNUMBEROF-CHARACTERS 10
第1栏第2栏第3栏
AB 1234 10
AB任意字符数10
您可以使用固定偏移量,因为您定义了字符串始终以两个字符开头,以两个字符结尾
DECLARE @str VARCHAR(100) = 'AB/1234/10'
SELECT LEFT(@str, CHARINDEX('/', @str) - 1) AS Column1
, SUBSTRING(@str, CHARINDEX('/', @str) + 1, CHARINDEX('/', SUBSTRING(@str, CHARINDEX('/', @str) + 1, LEN(@str))) - 1) AS Column2
, RIGHT(@str, CHARINDEX('/', REVERSE(@str)) - 1) AS Column3
下面是一个完整的工作示例:
DECLARE @tmp TABLE (
Merged nvarchar(max)
)
INSERT INTO @tmp SELECT N'AB/1234/10'
INSERT INTO @tmp SELECT N'AB/ANYNUMBEROF-CHARACTERS/10'
SELECT
LEFT(Merged,2) AS Column1,
SUBSTRING(Merged,4,LEN(Merged)-6) AS Column2,
RIGHT(Merged,2) AS Column3
FROM @tmp
我们减去字符串的长度减去一个常数(6=左两个字符,右两个字符,两个斜线),从中间提取可变长度部分
结果:
Column1 Column2 Column3
AB 1234 10
AB ANYNUMBEROF-CHARACTERS 10
第1栏第2栏第3栏
AB 1234 10
AB任意字符数10
一种方法是使用
PARSENAME
:
SELECT PARSENAME(REPLACE('AB/1234/10','/','.'), 3) Col1,
PARSENAME(REPLACE('AB/1234/10','/','.'), 2) Col2,
PARSENAME(REPLACE('AB/1234/10','/','.'), 1) Col3
这将用
替换
,并用PARSENAME
拉出字符串的每个部分
好处是它可以处理任何位置的任意长度的字符。限制是
PARSENAME
最多只能处理4个位置(在本例中,您使用的是3个),如果字符串中已经存在句点
,则将失败。一种方法是使用PARSENAME
:
SELECT PARSENAME(REPLACE('AB/1234/10','/','.'), 3) Col1,
PARSENAME(REPLACE('AB/1234/10','/','.'), 2) Col2,
PARSENAME(REPLACE('AB/1234/10','/','.'), 1) Col3
这将用
替换
,并用PARSENAME
拉出字符串的每个部分
好处是它可以处理任何位置的任意长度的字符。限制是
PARSENAME
最多只能处理4个位置(在本例中,您使用的是3个),如果字符串中已经存在句点
,则将失败。试试这个。这应该适用于任意数量的字符
DECLARE @str VARCHAR(100) = 'AB/1234/10'
SELECT LEFT(@str, CHARINDEX('/', @str) - 1) AS Column1
, SUBSTRING(@str, CHARINDEX('/', @str) + 1, CHARINDEX('/', SUBSTRING(@str, CHARINDEX('/', @str) + 1, LEN(@str))) - 1) AS Column2
, RIGHT(@str, CHARINDEX('/', REVERSE(@str)) - 1) AS Column3
试试这个。这应该适用于任意数量的字符
DECLARE @str VARCHAR(100) = 'AB/1234/10'
SELECT LEFT(@str, CHARINDEX('/', @str) - 1) AS Column1
, SUBSTRING(@str, CHARINDEX('/', @str) + 1, CHARINDEX('/', SUBSTRING(@str, CHARINDEX('/', @str) + 1, LEN(@str))) - 1) AS Column2
, RIGHT(@str, CHARINDEX('/', REVERSE(@str)) - 1) AS Column3
理想情况下,这项工作的一部分应该是永久性地分离这些数据。像这样存储多个元素违反1NF,处理起来非常痛苦。如果在建议的副本中使用类似的拆分器,则应避免使用可接受的答案,因为这是拆分字符串的可怕方式。相反,向下滚动到Aaron Bertrand的答案。这对性能更好。理想情况下,此练习的一部分应该是永久分离此数据。像这样存储多个元素违反1NF,处理起来非常痛苦。如果在建议的副本中使用类似的拆分器,则应避免使用可接受的答案,因为这是拆分字符串的可怕方式。相反,向下滚动到Aaron Bertrand的答案。它的性能要好得多。我非常喜欢这个技巧,但是如果任何源字符串包含一个点,它都会失败。处理句点的一个简单方法是先添加一个替换来替换一个句点。有点像^。当然,对于这个简单的字符串,你必须把它换回来,哪种类型的字符串开始有点过头了。不幸的是,我的案例中的任何或所有字符串都可能包含一个
,因此,虽然这个答案很好,但它不适用于我的案例。无论如何,谢谢。我非常喜欢这个技巧,但是如果任何源字符串包含一个点,它都会失败。处理句点的一个简单方法是先添加一个替换以替换掉一个句点。有点像^。当然,对于这个简单的字符串,你必须把它换回来,哪种类型的字符串开始有点过头了。不幸的是,我的案例中的任何或所有字符串都可能包含一个
,因此,虽然这个答案很好,但它不适用于我的案例。无论如何,谢谢。如果我能将多个答案标记为正确,我也会将这一个标记为正确,它本质上与我标记为正确的答案相同,但我真的很欣赏它的健壮性。它更适用于一般用途。谢谢。如果我能将多个答案标记为正确,我也会将这一个标记为正确,它本质上与我标记为正确的答案相同,但我真的很欣赏它的健壮性。它更适用于一般用途。非常感谢。