将字符串拆分为新列[重复]
Posted
技术标签:
【中文标题】将字符串拆分为新列[重复]【英文标题】:Split string into new column [duplicate] 【发布时间】:2015-08-01 18:26:30 【问题描述】:有一列包含以下内容,例如abcd/ef/g/hij
。
/
之间的字符是动态的而不是固定的。
我想在选择查询中将内容拆分为 4 个单独的新列。
已经回答的问题不同了,我想将/
分隔的字符串中的内容拆分成新的列。
【问题讨论】:
你的字符串中是否总是有 3 个/
或者列数也可以是动态的?
你能给出一个示例数据和预期的输出吗?
我将永远拥有 3 /。所以列数是固定的
我不完全理解这一点。您确定要列而不是行吗?哪些数据行将分配给列?您是否希望字符串拆分以创建临时/永久表,然后插入其中?
问题已关闭,就像我完成了答案一样,该链接仅描述了如何拆分 varchar。不要在列中分发它
【参考方案1】:
您需要使用 CHARINDEX 找到 / 字符的位置,并以这种方式分割字符串。这将是一个很大的表达式,因为要找到第三个斜线,您需要使用 CHARINDEX 的第三个参数,传递另一个 CHARINDEX 的结果,它也使用了它的第三个参数。除了最后一个(第四个)片段外,还需要使用 CHARINDEX 来查找和删除下一个斜线之后的文本。
这样的东西会提取第三个斜线后的文本:
RIGHT(s, CHARINDEX('/', s, CHARINDEX('/', s, CHARINDEX('/', s)+1)+1)+1)
剩下的交给你。
【讨论】:
【参考方案2】:您可以使用REPLACE
将'/'
替换为'.'
。然后使用PARSENAME
获取字符串的每个单独部分:
CREATE TABLE #tmp (str VARCHAR(50))
INSERT INTO #tmp VALUES
('abcd/ef/g/hij'),
('1111111/222/33/4444')
SELECT PARSENAME(x.s, 4) AS [1], PARSENAME(x.s, 3) AS [2],
PARSENAME(x.s, 2) AS [3], PARSENAME(x.s, 1) AS [4]
FROM #tmp
CROSS APPLY (SELECT REPLACE(str, '/', '.')) AS x(s)
输出:
1 2 3 4
---------------------
abcd ef g hij
1111111 222 33 4444
【讨论】:
有趣的解决方案,虽然我不会使用它,因为它不应该做 OP 想要的。它不适用于超过 4 个部分,并且还可能为[a]/[a]/[a]/[asd]
之类的字符串返回不正确的结果
@Roman OP 声明:我将永远有 3 个 /。(见评论),唯一的问题是 str
列中是否有 '.'
。但是也有一个解决方法(即在替换 '/'
s 之前用一个不存在的特殊字符替换 '.'
)。
[
符号会被您的解决方案删除吗?
@RomanPekar 好吧,这些符号将被PARSENAME
视为分隔符,因此将被排除在返回的字符串之外。此解决方案可能是最简单的但只能在str
列中没有'.'
、'['
或']'
的情况下使用。【参考方案3】:
如果您问我,最快的 ad-hoc 方法是将您的数据转换为 xml 并使用nodes()
方法:
declare @temp table (data nvarchar(max))
insert into @temp
select 'abcd/ef/g/hij' union all
select '1/2/3'
select t.data, n.c.value('.', 'nvarchar(max)')
from @temp as t
outer apply (select cast('<t>' + replace(t.data, '/', '</t><t>') + '</t>' as xml) as data) as d
outer apply d.data.nodes('t') as n(c)
【讨论】:
以上是关于将字符串拆分为新列[重复]的主要内容,如果未能解决你的问题,请参考以下文章