将嵌入的 CSV 文本拆分为单独的行
Split Embedded CSV Text Into Separate Rows
我正在尝试将以逗号分隔的数据拆分为单独的列(使用 SQL Server 2008)。我在这里看到过类似的问题,但就我而言,每一行中包含的数据都是逗号分隔和回车符分隔的 return-delimited.
示例:
Date Content
---- -------
1/1/2019 1, John, Doe
2, Jane, Doe
1/2/2019 1, John, Doe
2, Jane Doe
3, Mary, Smith
使用自定义拆分函数,我能够 return 一条记录的值:
SELECT * FROM Split_CTE((SELECT TOP 1 content FROM myTable), CHAR(10))
结果:
1,John,Doe
2,Jane,Doe
并且使用子字符串函数,我能够 return 每条记录的第一行:
SELECT dateRetrieved, SUBSTRING(content, 1, CHARINDEX(CHAR(10), content)-1) 作为 Row FROM myTable
结果:
1/1/2019 1,John,Doe
1/2/2019 1,John,Doe
但我想要返回的是:
Date Row First Last
1/1/2019 1 John Doe
1/1/2019 2 Jane Doe
1/2/2019 1 John Doe
1/2/2019 2 Jane Doe
1/2/2019 3 Mary Smith
有什么建议吗?
Cross Apply B 将使用 CRLF 分隔符拆分
交叉应用 C 并将逗号分隔的字符串从 B 解析为列
我应该注意到,每个 CROSS APPLY 都可以转换成 TVF
例子
Select A.Date
,C.*
From YourTable A
Cross Apply (
Select RetSeq = row_number() over (order by 1/0)
,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace([Content],char(13)+char(10),'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
From (Select Cast('<x>' + replace((Select replace(B.RetVal,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A
) C
Order by A.Date,C.Pos1
Returns
Date Pos1 Pos2 Pos3
2019-01-01 1 John Doe
2019-01-01 2 Jane Doe
2019-01-02 1 John Doe
2019-01-02 2 Jane Doe
2019-01-02 3 Mary Smith
我正在尝试将以逗号分隔的数据拆分为单独的列(使用 SQL Server 2008)。我在这里看到过类似的问题,但就我而言,每一行中包含的数据都是逗号分隔和回车符分隔的 return-delimited.
示例:
Date Content ---- ------- 1/1/2019 1, John, Doe 2, Jane, Doe 1/2/2019 1, John, Doe 2, Jane Doe 3, Mary, Smith
使用自定义拆分函数,我能够 return 一条记录的值:
SELECT * FROM Split_CTE((SELECT TOP 1 content FROM myTable), CHAR(10))
结果:
1,John,Doe 2,Jane,Doe
并且使用子字符串函数,我能够 return 每条记录的第一行:
SELECT dateRetrieved, SUBSTRING(content, 1, CHARINDEX(CHAR(10), content)-1) 作为 Row FROM myTable
结果:
1/1/2019 1,John,Doe 1/2/2019 1,John,Doe
但我想要返回的是:
Date Row First Last 1/1/2019 1 John Doe 1/1/2019 2 Jane Doe 1/2/2019 1 John Doe 1/2/2019 2 Jane Doe 1/2/2019 3 Mary Smith
有什么建议吗?
Cross Apply B 将使用 CRLF 分隔符拆分
交叉应用 C 并将逗号分隔的字符串从 B 解析为列
我应该注意到,每个 CROSS APPLY 都可以转换成 TVF
例子
Select A.Date
,C.*
From YourTable A
Cross Apply (
Select RetSeq = row_number() over (order by 1/0)
,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace([Content],char(13)+char(10),'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
From (Select Cast('<x>' + replace((Select replace(B.RetVal,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A
) C
Order by A.Date,C.Pos1
Returns
Date Pos1 Pos2 Pos3
2019-01-01 1 John Doe
2019-01-01 2 Jane Doe
2019-01-02 1 John Doe
2019-01-02 2 Jane Doe
2019-01-02 3 Mary Smith