T-SQL从字符串和计数生成序列

时间:2015-08-06 12:52:29

标签: tsql csv

我需要从CSV字符串和最大计数开始生成序列。 当序列超过时,我需要再次启动序列并继续直到我使COUNT变量饱和

我有以下CSV:

A,B,C,D

为了从这个CSV中获取4行,我使用XML和以下语句:

    SET @xml_csv = N'<root><r>' + replace('A, B, C, D',',','</r><r>') + '</r></root>'                   
    SELECT
        REPLACE(t.value('.','varchar(max)'), ' ', '') AS [delimited items]
    FROM 
        @xml_csv.nodes('//root/r') AS a(t)

现在我的SELECT返回以下输出:

|-------------|
| A           |
| B           |
| C           |
| D           |

假设我将@count变量设置为9,我需要输出以下内容:

|--|-----------|
|1 |A          |
|2 |B          |
|3 |C          |
|4 |D          |
|5 |A          |
|6 |B          |
|7 |C          |
|8 |D          |
|9 |A          |

我试图加入一个名为master的表.. [spt_values]但我得到一个COUNT = 10 10行A,10行B等等,而我需要序列有序并重复直到它饱和

1 个答案:

答案 0 :(得分:2)

基本上你是在正确的道路上。将分割结果与数字表连接将获得正确的输出。

我选择使用不同的功能来分割csv数据,因为它也使用数字表进行分割。 (取自this great article

首先,如果您还没有数字表,请创建一个。这是我链接到的文章中使用的脚本:

SET NOCOUNT ON;

DECLARE @UpperLimit INT = 1000;

WITH n AS
(
    SELECT
        x = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
    FROM       sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
    CROSS JOIN sys.all_objects AS s3
)
SELECT Number = x
  INTO dbo.Numbers
  FROM n
  WHERE x BETWEEN 1 AND @UpperLimit;

GO

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers(Number) 
    WITH (DATA_COMPRESSION = PAGE);
GO

然后,创建拆分功能:

CREATE FUNCTION dbo.SplitStrings_Numbers
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN
   (
       SELECT Item = SUBSTRING(@List, Number, 
         CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number)
       FROM dbo.Numbers
       WHERE Number <= CONVERT(INT, LEN(@List))
         AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter
   );
GO

下一步:使用数字表加入拆分结果:

DECLARE @Csv varchar(20) = 'A,B,C,D'

SELECT TOP 10 Item
FROM dbo.SplitStrings_Numbers(@Csv, ',')
CROSS JOIN Numbers
ORDER BY Number

输出:

Item
----
A
B
C
D
A
B
C
D
A
B

非常感谢Aaron Bertrand分享他的知识。