【发布时间】:2017-09-07 20:15:52
【问题描述】:
所以,我的第一篇文章不是一个问题,而是一个声明!对不起。
我需要将存储在 VarChar 表列中的分隔字符串转换为同一记录的多个/单独列。 (它是 COTS 软件;所以请不要费心告诉我该表是如何设计错误的。)在互联网广告 nauseum 搜索如何创建通用单行调用来做到这一点之后 - 并找到了很多不这样做的方法 -我创建了自己的。 (这个名字没有真正的创意。)
返回:具有以 [Col1] 开头的按顺序编号/命名的列的表。如果未提供输入值,则返回空字符串。如果提供的值少于 32 个,则最后一个值之后的所有值都将返回为 null。如果提供的值超过 32 个,则会被忽略。
先决条件:数字/计数表(幸运的是,我们的数据库已经包含“dbo.numbers”)。
假设:不超过 32 个分隔值。 (如果您需要更多,请更改“WHERE tNumbers.Number BETWEEN 1 AND XXX”,并添加更多预先命名的列“,[Col33]...,[ColXXX]”。)
问题:第一列总是被填充,即使 @InputString 为 NULL。
--======================================================================
--SMOZISEK 2017/09 CREATED
--======================================================================
CREATE FUNCTION dbo.fStringToPivotTable
(@InputString VARCHAR(8000)
,@Delimiter VARCHAR(30) = ','
)
RETURNS TABLE AS RETURN
WITH cteElements AS (
SELECT ElementNumber = ROW_NUMBER() OVER(PARTITION BY @InputString ORDER BY (SELECT 0))
,ElementValue = NodeList.NodeElement.value('.','VARCHAR(1022)')
FROM (SELECT TRY_CONVERT(XML,CONCAT('<X>',REPLACE(@InputString,@Delimiter,'</X><X>'),'</X>')) AS InputXML) AS InputTable
CROSS APPLY InputTable.InputXML.nodes('/X') AS NodeList(NodeElement)
)
SELECT PivotTable.*
FROM (
SELECT ColumnName = CONCAT('Col',tNumbers.Number)
,ColumnValue = tElements.ElementValue
FROM DBO.NUMBERS AS tNumbers --DEPENDENT ON ANY EXISTING NUMBER/TALLY TABLE!!!
LEFT JOIN cteElements AS tElements
ON tNumbers.Number = tElements.ElementNumber
WHERE tNumbers.Number BETWEEN 1 AND 32
) AS XmlSource
PIVOT (
MAX(ColumnValue)
FOR ColumnName
IN ([Col1] ,[Col2] ,[Col3] ,[Col4] ,[Col5] ,[Col6] ,[Col7] ,[Col8]
,[Col9] ,[Col10],[Col11],[Col12],[Col13],[Col14],[Col15],[Col16]
,[Col17],[Col18],[Col19],[Col20],[Col21],[Col22],[Col23],[Col24]
,[Col25],[Col26],[Col27],[Col28],[Col29],[Col30],[Col31],[Col32]
)
) AS PivotTable
;
GO
测试:
SELECT *
FROM dbo.fStringToPivotTable ('|Height|Weight||Length|Width||Color|Shade||Up|Down||Top|Bottom||Red|Blue|','|') ;
用法:
SELECT 1 AS ID,'Title^FirstName^MiddleName^LastName^Suffix' AS Name
INTO #TempTable
UNION SELECT 2,'Mr.^Scott^A.^Mozisek^Sr.'
UNION SELECT 3,'Ms.^Jane^Q.^Doe^'
UNION SELECT 5,NULL
UNION SELECT 7,'^Betsy^^Ross^'
;
SELECT SourceTable.*
,ChildTable.Col1 AS ColTitle
,ChildTable.Col2 AS ColFirst
,ChildTable.Col3 AS ColMiddle
,ChildTable.Col4 AS ColLast
,ChildTable.Col5 AS ColSuffix
FROM #TempTable AS SourceTable
OUTER APPLY dbo.fStringToPivotTable(SourceTable.Name,'^') AS ChildTable
;
不,我没有测试任何计划(我只是需要它来工作)。 哦,是的:SQL Server 2012 (12.0 SP2)
评论?更正?增强功能?
【问题讨论】:
-
你的问题到底是什么?
标签: sql-server tsql parsing csv