假设我有一个这样的表,在一列中有一个未确定的逗号分隔值:
thingID personID
1 123,234,345
2 456,567
我想把它变成这样的形式:
thingID personID
1 123
1 234
1 345
2 456
2 567
这样做的最佳选择是什么? 哦,我应该提一下数据是在SQL 2008 R2数据库中,所以我可能无法使用最新的功能。
答案 0 :(得分:0)
将CROSS APPLY
与字符串拆分功能一起使用
要找到最适合您的字符串拆分功能,请阅读Aaron Bertrand的Split strings the right way – or the next best way.
对于本演示,我选择使用SplitStrings_XML
函数,因为它是文章中第一个纯t-sql函数:
CREATE FUNCTION dbo.SplitStrings_XML
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
GO
现在我们有了一个字符串拆分功能,创建并填充样本表(请在将来的问题中保存这一步骤):
DECLARE @T AS TABLE
(
thingID int,
personID varchar(max)
)
INSERT INTO @T VALUES
(1, '123,234,345'),
(2, '456,567')
查询:
SELECT thingId, Item
FROM @T
CROSS APPLY dbo.SplitStrings_XML(personID, ',')
结果:
thingId Item
1 123
1 234
1 345
2 456
2 567
答案 1 :(得分:0)
有几种方法可以做到这一点。以下是SQL Server 2008的两种方法:
XML-Method:要求字符串允许xml-trick(没有无效的XML字符)
SELECT a.thingID, Split.a.value('.', 'VARCHAR(100)') AS Data
FROM (SELECT OtherID,
CAST('<M>' + REPLACE(personID, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM table1) AS A CROSS APPLY Data.nodes ('/M') AS Split(a);
递归方法:
;WITH tmp(thingID, DataItem, Data) AS (
SELECT thingID, LEFT(personID, CHARINDEX(',', personID + ',') - 1),
STUFF(personID, 1, CHARINDEX(',', personID + ','), '')
FROM table1
UNION ALL
SELECT thingID, LEFT(personID, CHARINDEX(',', personID + ',') - 1),
STUFF(personID, 1, CHARINDEX(',', personID + ','), '')
FROM tmp
WHERE Data > ''
)
SELECT thingID, DataItem AS personID
FROM tmp