2016-06-10 48 views
2

我是SQL Server的新手,我正在处理以下问题。SQL Server:将多个字符串分隔成一行

比方说,我有一列看起来像这样:

ID String 
------------------------- 
1 Today is a good day! 
2 Whatever 
3 Hello my friend 

所以我的目标是将这些句子拆分成这样:

ID String1 String2 String3 String4 String5 
------------------------------------------------------ 
1 Today  is   a   good  day! 
2 Whatever 
3 Hello  my   friend 

我使用此代码尝试:

CREATE FUNCTION [dbo].[SplitString] 
    (@str nvarchar(max), 
     @separator char(1)) 
RETURNS TABLE 
AS 
    RETURN (
     WITH tokens(p, a, b) AS 
     (
      SELECT 
       CAST(1 AS BIGINT), 
       CAST(1 AS BIGINT), 
       CHARINDEX(@separator, @str) 

      UNION ALL 

      SELECT 
       p + 1, 
       b + 1, 
       CHARINDEX(@separator, @str, b + 1) 
      FROM 
       tokens 
      WHERE 
       b > 0 
     ) 
     SELECT 
      --p-1 ItemIndex, 
      SUBSTRING(@str, a, 
          CASE WHEN b > 0 THEN b-a 
           ELSE LEN(@str) 
          END) AS Item 
     FROM tokens) 
GO 

我在这里找到了Stackoverflow。

它似乎工作,单个字符串,但它不适用于多个字符串。 而且它把每一个字在新行是这样的:

Item 
Today 
is 
a 
good 
day! 

那么,如何调整代码,因此它不想要的?

还有一个问题是,我并不真正知道每个字符串中的字数。

所以它可能不同,例如,从1个字到100个字。

如果有人能够帮助我解决这个问题,我将非常高兴,因为我只开始学习如何使用SQL。

谢谢! MG

+1

看起来像在scool家庭作业。如果对列号没有限制,则必须使用动态查询。 – xdd

+0

这里有一些更好的表演分路器选项。 http://sqlperformance.com/2012/07/t-sql-queries/split-strings为了回到列中,您需要使用动态交叉表或动态数据透视表。 –

+0

对于刚刚学习t-sql的人来说,这是一个相当先进的问题。 –

回答

3

随着XML的帮助:

DECLARE @xml xml 

;WITH cte AS (
SELECT * 
FROM (VALUES 
(1, 'Today is a good day!'), 
(2, 'Whatever'), 
(3, 'Hello my friend') 
) as t(ID, String) 
) 

SELECT @xml = (
SELECT CAST('<i id="' + CAST(ID as nvarchar(10)) + '"><w>' + REPLACE(REPLACE(String,' ','</w><w>'),'&','&amp;') + '</w></i>' as xml) 
FROM cte 
FOR XML PATH('') 
) 

SELECT t.v.value('@id','int') as ID, 
     t.v.value('w[1]','nvarchar(10)') as String1, 
     t.v.value('w[2]','nvarchar(10)') as String2, 
     t.v.value('w[3]','nvarchar(10)') as String3, 
     t.v.value('w[4]','nvarchar(10)') as String4, 
     t.v.value('w[5]','nvarchar(10)') as String5, 
     t.v.value('w[6]','nvarchar(10)') as String6 
FROM @xml.nodes('/i') as t(v) 

输出:

ID   String1 String2 String3 String4 String5 String6 
----------- ---------- ---------- ---------- ---------- ---------- ---------- 
1   Today  is   a   good  day!  NULL 
2   Whatever NULL  NULL  NULL  NULL  NULL 
3   Hello  my   friend  NULL  NULL  NULL 

编辑

要与实际使用表:

DECLARE @xml xml 

SELECT @xml = (
SELECT CAST('<i id="' + CAST(ID as nvarchar(10)) + '"><w>' + REPLACE(big_string,' ','</w><w>') + '</w></i>' as xml) 
FROM [table] 
FOR XML PATH('') 
) 

SELECT t.v.value('@id','int') as ID, 
     t.v.value('w[1]','nvarchar(10)') as String1, 
     t.v.value('w[2]','nvarchar(10)') as String2, 
     t.v.value('w[3]','nvarchar(10)') as String3, 
     t.v.value('w[4]','nvarchar(10)') as String4, 
     t.v.value('w[5]','nvarchar(10)') as String5, 
     t.v.value('w[6]','nvarchar(10)') as String6, 
     t.v.value('w[7]','nvarchar(10)') as String7 
FROM @xml.nodes('/i') as t(v) 
+0

所以这是我正在寻找的代码。 一个简短的问题:是否可以使用大于6个字的字符串? 它是否删除单词[7:]?这样可以。 – mgruber

+1

是的,可以处理任意数量的单词。 – gofr1

+0

好的!所以我现在要做的就是根据我的实际需要调整代码。我有一个Table'table',我只想让一列'big_string'成为代码和输出的一部分。我自己尝试过,但是我没有像那样调整它。 – mgruber

1

我编辑了你的代码。尝试运行这个。根据要追加的行,动态创建列。结果是这样的:return rows 它没有按顺序排列。尝试编辑上面的代码以包含您的ID,以便它再次按顺序排列。

DECLARE @TBL TABLE (Id int, Description varchar(max)) 
CREATE table #tblResult(Description varchar(max)) 

INSERT INTO @TBL 
SELECT 1, 'Today is a good day!' 

DECLARE @separator varchar(1) = ' ', @str varchar(max) 
SELECT @str = Description FROM @TBL 


    ;WITH tokens(p, a, b) AS 
    (
     SELECT 
      CAST(1 AS BIGINT), 
      CAST(1 AS BIGINT), 
      CHARINDEX(@separator, @str) 

     UNION ALL 

     SELECT 
      p + 1, 
      b + 1, 
      CHARINDEX(@separator, @str, b + 1) 
     FROM 
      tokens 
     WHERE 
      b > 0 
    ) 

    INSERT INTO #tblResult 
    SELECT 
     SUBSTRING(@str, a, 
         CASE WHEN b > 0 THEN b-a 
          ELSE LEN(@str) 
         END) AS Item 
         FROM tokens 

    DECLARE @x nvarchar(MAX), @query nvarchar(MAX) 

    select @x = STUFF((SELECT ',' + QUOTENAME(Description) 
       from #tblResult 
       group by Description 
       order by Description 
     FOR XML PATH(''), TYPE 
     ).value('.', 'nvarchar(MAX)') 
    ,1,1,'') 


    set @query = N'SELECT ' + @x + N' from 
     (
      select Description 
      from #tblResult 
     ) x 
     pivot 
     (
      max(Description) 
      for Description in (' + @x + N') 
     ) p ' 

    exec sp_executesql @query; 


    drop table #tblResult 
+0

这段代码似乎工作得很好,但输出不正确!? – mgruber

相关问题