SQL Server 2012将几个逗号分隔的值转换为表行/列
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server 2012将几个逗号分隔的值转换为表行/列相关的知识,希望对你有一定的参考价值。
目前,我有一个以下列方式存储历史数据的表。我无法控制此服务器或数据的存储方式。
ID | FName | LName |Stuff| More
--------+---------+---------+-----+------
1,2,3,4 | j,p,g,r | l,m,h,s | ,,, | a,,b,
我需要将这些数据放入结果集中,以便它采用以下格式:
ID | FName | LName |Stuff| More
--------+---------+---------+-----+------
1 | j | l | | a
2 | p | m | |
3 | g | h | | b
4 | r | s | |
我想避免使用函数,因为我不确定我将对其他环境中的服务器进行访问。我尝试过使用xml和cross apply,我可以为一个奇异的字段工作,但我似乎无法让全表工作。
任何建议将不胜感激,
谢谢~JM
答案
它可以通过递归查询来完成
;WITH CTE(ID, ID_tmp, FName, FName_tmp, LName, LName_tmp, Stuf, Stuf_tmp, more, more_tmp)
AS
(
SELECT CAST(LEFT(ID, CHARINDEX(',',ID+',')-1) AS NVARCHAR(50)) ID,
STUFF(ID, 1, CHARINDEX(',',ID+','), '') ID_tmp,
CAST(LEFT(FName, CHARINDEX(',',FName+',')-1) AS NVARCHAR(50)) FName,
STUFF(FName, 1, CHARINDEX(',',FName+','), '') ID_tmp,
CAST(LEFT(LName, CHARINDEX(',',LName+',')-1) AS NVARCHAR(50)) LName,
STUFF(LName, 1, CHARINDEX(',',LName+','), '') LName_tmp,
CAST(LEFT(Stuf, CHARINDEX(',',Stuf+',')-1) AS NVARCHAR(50)) Stuf,
STUFF(Stuf, 1, CHARINDEX(',',Stuf+','), '') Stuf_tmp,
CAST(LEFT(more, CHARINDEX(',',more+',')-1) AS NVARCHAR(50)) more,
STUFF(more, 1, CHARINDEX(',',more+','), '') more_tmp
FROM TAB
UNION ALL
SELECT CAST(LEFT(ID_tmp, CHARINDEX(',',ID_tmp+',')-1) AS NVARCHAR(50)) ID,
STUFF(ID_tmp, 1, CHARINDEX(',',ID_tmp+','), '') ID_tmp,
CAST(LEFT(FName_tmp, CHARINDEX(',',FName_tmp+',')-1) AS NVARCHAR(50)) FName,
STUFF(FName_tmp, 1, CHARINDEX(',',FName_tmp+','), '') FName_tmp,
CAST(LEFT(LName_tmp, CHARINDEX(',',LName_tmp+',')-1) AS NVARCHAR(50)) LName,
STUFF(LName_tmp, 1, CHARINDEX(',',LName_tmp+','), '') LName_tmp,
CAST(LEFT(Stuf_tmp, CHARINDEX(',',Stuf_tmp+',')-1) AS NVARCHAR(50)) Stuf,
STUFF(Stuf_tmp, 1, CHARINDEX(',',Stuf_tmp+','), '') Stuf_tmp,
CAST(LEFT(more_tmp, CHARINDEX(',',more_tmp+',')-1) AS NVARCHAR(50)) more,
STUFF(more_tmp, 1, CHARINDEX(',',more_tmp+','), '') more_tmp
FROM CTE
WHERE ID_tmp > ''
)
SELECT ID, FName , LName, stuf, more
FROM CTE
另一答案
如果您想避免使用UDF,那么XML nodes()方法仍然能够通过使用多个CTE
方法来帮助您。
WITH cteId AS
(
SELECT Ids.value('.', 'INT') Id FROM
(
SELECT
cast('<x>'+replace(Id, ',', '</x><x>')+'</x>' as xml) as Id
FROM table t
)a CROSS APPLY Id.nodes ('/x') as split(Ids)
), ctefname AS
(
SELECT
row_number() over (order by (select 1)) Seq,
FNames.value('.', 'varchar') FNames FROM
(
SELECT
cast('<x>'+replace(FName, ',', '</x><x>')+'</x>' as xml) as FName
FROM table t
)a CROSS APPLY FName.nodes ('/x') as split(FNames)
), cteLname AS
(
SELECT
row_number() over (order by (select 1)) Seq,
LNames.value('.', 'varchar') LNames FROM
(
SELECT
cast('<x>'+replace(LName, ',', '</x><x>')+'</x>' as xml) as LName
FROM table t
)a CROSS APPLY LName.nodes ('/x') as split(LNames)
), ...
SELECT
id.Id, fn.FNames, ln.LNames, ...
FROM cteId id
INNER JOIN ctefname fn on fn.Seq = id.Id
INNER JOIN cteLname ln on ln.Seq = id.Id
...
以上是关于SQL Server 2012将几个逗号分隔的值转换为表行/列的主要内容,如果未能解决你的问题,请参考以下文章
在sql server数据库中查询一个用逗号分隔的字段的问题