假设我有一个表格,如
ItemID ClassID
------------------------
1 10, 13, 12
2 5, 7
并希望将数据复制到另一个表中,如此
ItemID Numbering ClassID
----------------------------------
1 1 10
1 2 13
1 3 12
2 1 5
2 2 7
ClassID
字段分隔为单独的行,保留第一个表中的顺序Numbering
行。 Numbering
列对每批ClassID
都有连续的整数,这就是ClassID
需要按顺序排列的原因。我尝试使用以下功能:
CREATE FUNCTION dbo.Split
(
@String NVARCHAR(MAX)
)
RETURNS @SplittedValues TABLE(
Value INT
)
AS
BEGIN
DECLARE @SplitLength INT
DECLARE @Delimiter VARCHAR(10)
SET @Delimiter = ','
WHILE len(@String) > 0
BEGIN
SELECT @SplitLength = (CASE charindex(@Delimiter, @String)
WHEN 0 THEN
datalength(@String) / 2
ELSE
charindex(@Delimiter, @String) - 1
END)
INSERT INTO @SplittedValues
SELECT cast(substring(@String, 1, @SplitLength) AS INTEGER)
WHERE
ltrim(rtrim(isnull(substring(@String, 1, @SplitLength), ''))) <> '';
SELECT @String = (CASE ((datalength(@String) / 2) - @SplitLength)
WHEN 0 THEN
''
ELSE
right(@String, (datalength(@String) / 2) - @SplitLength - 1)
END)
END
RETURN
END
但它只是部分有效。它会将行复制正确的次数(例如,ItemID=1
为三次,上例中为ItemID=2
两次),但它们是该行的精确副本(所有这些都是'10,13, 12')和逗号分隔的部分不分开。函数中也没有任何内容可以添加到Numbering
列。
所以,我有两个问题:如何修改上述函数以拆分ClassID
字符串,以及我添加什么来正确增加Numbering
列?
谢谢!
答案 0 :(得分:4)
我使用递归CTE来完成它。
WITH SplitCTE AS
(
SELECT
itemid,
LEFT(ClassID,CHARINDEX(',',ClassID)-1) AS ClassID
,RIGHT(ClassID,LEN(ClassID)-CHARINDEX(',',ClassID)) AS remaining
FROM table1
WHERE ClassID IS NOT NULL AND CHARINDEX(',',ClassID)>0
UNION ALL
SELECT
itemid,
LEFT(remaining,CHARINDEX(',',remaining)-1)
,RIGHT(remaining,LEN(remaining)-CHARINDEX(',',remaining))
FROM SplitCTE
WHERE remaining IS NOT NULL AND CHARINDEX(',',remaining)>0
UNION ALL
SELECT
itemid,remaining,null
FROM SplitCTE
WHERE remaining IS NOT NULL AND CHARINDEX(',',remaining)=0
)
SELECT
itemid,
row_number() over (partition by itemid order by cast(classid as int) asc) as Numbering,
cast (ClassID as int) as ClassID
FROM
SplitCTE
UNION ALL
select
ItemId,
1,
cast(classid as int)
FROM table1
WHERE ClassID IS NOT NULL AND CHARINDEX(',',ClassID) = 0
答案 1 :(得分:0)
DECLARE @t TABLE( ID INT IDENTITY, data VARCHAR(50)) INSERT INTO @t(data) SELECT '10, 13, 12' INSERT INTO @t(data) SELECT '5, 7'select F1.id,O.splitdata, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY (SELECT 1))
from ( select *,cast(''+replace(F.data,',','')+'' as XML) as xmlfilter from @t F
)F1
cross apply ( select fdata.D.value('.','varchar(50)') as splitdata from f1.xmlfilter.nodes('X') as fdata(D) ) O