Sql server 在SQL Server中拆分以逗号分隔的字符串并选择为具有联接的列?

Sql server 在SQL Server中拆分以逗号分隔的字符串并选择为具有联接的列?,sql-server,Sql Server,我有一张这样的桌子: name orderid bambino 4,5,6,7,8 我们如何将orderid列中的值分成不同的列,如下面的示例所示 name order1 order2 order3 order4 order5 bambino 4 5 6 7 8 如果在orderid列中有固定数量的值,此问题可能会帮助您: 使用xml然后旋转的一些技巧: DECLARE @t TABLE ( name VARCH

我有一张这样的桌子:

name     orderid
bambino  4,5,6,7,8
我们如何将
orderid
列中的值分成不同的列,如下面的示例所示

name     order1 order2 order3 order4 order5
bambino  4      5      6      7      8

如果在orderid列中有固定数量的值,此问题可能会帮助您:


使用
xml
然后旋转的一些技巧:

DECLARE @t TABLE
    (
      name VARCHAR(20) ,
      orderid VARCHAR(20)
    )

INSERT  INTO @t
VALUES  ( 'chao', '1,2,3' ),
        ( 'bambino', '4,5,6,7,8' );
WITH    cte
          AS ( SELECT   name ,
                        Split.a.value('.', 'VARCHAR(100)') AS orderid ,
                        ROW_NUMBER() OVER ( PARTITION BY name ORDER BY ( SELECT
                                                              NULL
                                                              ) ) rn
               FROM     ( SELECT    name ,
                                    CAST ('<M>' + REPLACE(orderid, ',',
                                                          '</M><M>') + '</M>' AS XML) AS orderid
                          FROM      @t
                        ) AS A
                        CROSS APPLY orderid.nodes('/M') AS Split ( a )
             )
    SELECT  name ,
            [1] AS order1 ,
            [2] AS order2 ,
            [3] AS order3 ,
            [4] AS order4 ,
            [5] AS order5 ,
            [6] AS order6 ,
            [7] AS order7 ,
            [8] AS order8 ,
            [9] AS order9 ,
            [10] AS order10
    FROM    cte PIVOT( MAX(orderid) FOR rn IN ( [1], [2], [3], [4], [5], [6],
                                                [7], [8], [9], [10] ) ) p
这是一个非常好的网页,介绍如何将逗号分隔的字符串拆分为行。有很多不同的方法,所以选择一种适合你需要的方法。(例如CLR将比XML“黑客”更快,但这可能不是一个问题。)


一旦您将数据排成行,就可以使用
PIVOT
将其转换为列。如果您不知道将有多少列,您可能必须在动态SQL中执行此操作。

最简单的动态查询是,如果您在
orderid
列中有一百万个订单,则此查询不会介意

declare @name as nvarchar(50), @orderid as nvarchar(50), @dorders as nvarchar(max)='',@count as int = 1
select @name=name, @orderid=orderid from abc -- add here where clause to select particular row
select @dorders = @dorders + splitdata + ' as [Order'+convert(nvarchar(10),@count)+'],', @count = @count + 1 from fnsplitstring(@orderid,',')
set @dorders = SUBSTRING(@dorders,0,len(@dorders))
declare @Dsql as nvarchar(max) = 'select '''+@name+''' as name, '+@dorders
exec (@Dsql)
供参考

哦。。并添加此功能,无论如何它都很有用

CREATE FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
        IF @end = 0  
            SET @end = LEN(@string) + 1

        INSERT INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)

    END 
    RETURN 
END
创建函数[dbo].[fnSplitString]
( 
@字符串NVARCHAR(最大值),
@分隔符字符(1)
) 
返回@output TABLE(splitdata-NVARCHAR)(最大值)
) 
开始
声明@start INT、@end INT
选择@start=1、@end=CHARINDEX(@delimiter、@string)
而@start
当您的表有2行或更多行时会发生什么?旁注:如果您打算使用并推荐基于sql的拆分器,Jeff Moden创建的DelimitedSplit8K,实际上就是这样。您可以阅读更多关于它及其性能比较的信息。OP在这里询问了名为
bambino
的单行,如果他补充问题,我将不得不更改所提到的查询表,该表的示例数据为
bambino
。您是否要假设该表始终只有一行?我假设他每次提取一行作为结果集(如图所示),他可以通过添加where子句来选择哪一行,我在其中分配变量值(即,
@name,@orderid
)。我添加了一些评论来支持我的论点,非常感谢@Giorgi Nakeuri让我试试
CREATE FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
        IF @end = 0  
            SET @end = LEN(@string) + 1

        INSERT INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)

    END 
    RETURN 
END