将字符串分隔为列

时间:2015-06-08 18:21:59

标签: sql-server-2008 tsql string-parsing

数据:

COL1  COL2  COL3 DEPTH
URL1  URL2         2
URL2  URL3         2
URL3  URL4  URL5   3
URL1  URL2  URL3   3

在上面的数据中,Tree列由以“||”分隔的字符串组成。我需要转换上面的数据,以便我有3列(因为在这个例子中最大深度是3),结果应如下所示:

balance

在上面的示例中,最大深度为3,但在现实世界中,它可以是N数。

2 个答案:

答案 0 :(得分:0)

美好的一天,

乍一看,我们需要使用用户定义的SPLIT函数,但由于每个字符串中的值的数量不超过4,因此有一个更简单,可能更好的解决方案。我们只需要使用内置的PARSENAME function

我没有测试代码,但解决方案应该是这样的:

SELECT PARSENAME(REPLACE(Tree,'||','.'), 1) as col1, PARSENAME(REPLACE(Tree,'||','.'), 2) as col2, PARSENAME(REPLACE(Tree,'||','.'), 3) as col3, Depth
from TableName
  • 我替换了||带点,因为PARSENAME解析按点分割的名称。这就是诀窍: - )

  • 我在sqlsaturday #360的演讲中实际上提到了这样的例子。你可以see the presentation。讲座是关于为什么要使用SQLCLR,而不是那么重要何时使用它而不是transact-SQL。但我也谈到了什么时候不使用它,这就是那里的例子之一。

  • 无论如何!如果你打算使用SPLIT函数,那么你应该使用SQLCLR而不是T-SQL,as you can see here

答案 1 :(得分:0)

试试这个,您只需要输入您的输入表,输出表,分隔线和列进行拆分。与PARSENAME功能不同,它可以处理3个以上的深度。

测试了100,000条记录和30条拆分列。创建所需的输出需要10秒。

Declare @Delimiter nvarchar(10) = '||'
Declare @InputTable nvarchar(2000) = '<<input table name>>'
Declare @OutputTable nvarchar(2000) = '<<output table name>>'
Declare @ColumnToSplit nvarchar(2000) = '<<column to split>>'


Declare @lsql nvarchar(max)
Declare @treeDepth int

If Object_id('dbo.treeDepth') is not null 
Drop table dbo.treeDepth

CREATE TABLE dbo.treeDepth (depth INT)

declare @ltext nvarchar(max)= 'Select max(1+(len('+@ColumnToSplit+')- len(Replace('+@ColumnToSplit+','''+@Delimiter+''','''')))/(len('''+@Delimiter+'''))) from '+@InputTable

insert dbo.treeDepth EXEC(@ltext)

Select @lsql = isnull(@lsql+',','') + 
'xmlname.value(''/Node[1]/Node['+cast(number+1 as nvarchar)+']'',''varchar(1000)'') AS Col_'+cast(number+1 as nvarchar)+''
from master..spt_values where type = 'P' and number < (Select * from dbo.treeDepth)

set @lsql = '
WITH ForXML
AS
(
    SELECT *,
    CONVERT(XML,''<Node><Node>''  
    + REPLACE('+@ColumnToSplit+','''+@Delimiter+''', ''</Node><Node>'') + ''</Node></Node>'') AS xmlname
      FROM '+@InputTable+'
)

Select *, '+@lsql+' Into '+@OutputTable+' From ForXML


Alter table '+@OutputTable+' 
Drop column xmlname
' 

EXEC(@lsql)
相关问题