使用TSQL将逗号分隔的字符串表行拆分为单独的行

5
假设我有一个查询返回以下内容。
ID       SomeValue
1        a,b,c,d
2        e,f,g

我希望您将此翻译为如下内容:

ID       SomeValue
1        a
1        b
1        c
1        d
2        e
2        f
2        g

我已经有一个名为Split的UDF函数,它可以接受一个字符串和一个分隔符,并将其作为一个名为[Value]的单列表返回。鉴于此,应该如何编写SQL来实现这一点?


可能是Tsql split string的重复问题 - Karl Kieninger
@AlvinThompson 我相信实际上已经有好几个 brazillion 次了 ;-). - Solomon Rutzky
实际上,那个问题并没有完全回答这个问题。我已经有一个分割字符串的函数了。我想要的是一个单一的查询,将一个表中的结果拆分到第二个表中。无论如何,下面的答案解决了这个问题。 - Stewart Alan
3个回答

9

或者,您可以这样使用XML:

DECLARE @yourTable TABLE(ID INT,SomeValue VARCHAR(25));

INSERT INTO @yourTable
VALUES  (1,'a,b,c,d'),
        (2,'e,f,g');

WITH CTE
AS
(
    SELECT  ID,
            [xml_val] = CAST('<t>' + REPLACE(SomeValue,',','</t><t>') + '</t>' AS XML)
    FROM @yourTable
)

SELECT  ID,
        [SomeValue] = col.value('.','VARCHAR(100)')
FROM CTE
CROSS APPLY [xml_val].nodes('/t') CA(col)

1
这是我在此网站上看到的所有答案中使用XML的最简单的示例。谢谢! - 4AM
1
太棒了!我已经根据您的答案进行了调整,以处理我正在开发的项目中没有分隔符的字符串。 - Mark Kram

3

你使用cross apply。类似于这样:

select t.id, s.val as SomeValue
from table t cross apply
     dbo.split(SomeValue, ',') as s(val);

你能分享一下你使用的 "dbo.split" 函数吗? - B3S
@B3S . . . SQL Server在2016年提供了其中一个。否则,您可以通过谷歌搜索“SQL Server split”轻松获得它们。 - Gordon Linoff
正确的系统函数应该使用STRING_SPLIT而不是dbo.split。请参考https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql。 - GoldBishop
是的,dbo.split 通常是用户定义的函数,在大多数实现中都是如此。只是想说一下,在2016年,有一个系统函数可以执行我们必须实现的功能。 - GoldBishop

0

我知道这是一个较旧的帖子,但我想添加我的解决方案,以便将来可以找到它。我不得不对Stephan's的解决方案进行微调,以考虑不包含分隔符的值:

DECLARE @yourTable TABLE(ID INT,SomeValue VARCHAR(25));

INSERT INTO @yourTable
VALUES  (1,'a,b,c,d'),
        (2,'e'),
        (3,'f'),
        (4,'g,h,i');

WITH CTE
AS
(
    SELECT  ID,
            [xml_val] = CAST('<t>' +
                                CASE WHEN  CHARINDEX(',', SomeValue) > 0
                                    THEN REPLACE(SomeValue,',','</t><t>') 
                                    ELSE SomeValue
                                END + '</t>' AS XML)
    FROM @yourTable
)

SELECT  ID,
        [SomeValue] = col.value('.','VARCHAR(100)')
FROM CTE
CROSS APPLY [xml_val].nodes('/t') CA(col)

谢谢您查看这个问题,Mark。但是您是否尝试测试我针对没有分隔符的值提出的解决方案?您会注意到,我的解决方案通过在CAST表达式中添加'<t>'和'</t>'来解决这个问题,因此无论是否有任何分隔符,它都可以正常工作。您的解决方案也可以工作,但我认为它增加了不必要的工作量。 - Stephan
嗯,我遇到了一个错误(现在想想很可能是数据问题),而且时间也很紧迫,所以我只需要让它对我起作用。我下周会再试一次并告诉你结果。 - Mark Kram

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接