如何在SQL Server中的逗号之间查找所有字符串

时间:2019-02-20 07:09:05

标签: sql sql-server tsql

我想以表格格式显示字符串,如下所示:

对于像'hi,is,1,question,thanks,.,.,n'

这样的字符串

我需要这个结果:

column1    column2  column3   column4  ..... column
hi         is       1         question ..... n

2 个答案:

答案 0 :(得分:1)

这不是小事。您会发现很多示例,如何将字符串拆分为一组片段。您会发现很多示例,这些示例如何将行集转换为单行。但是-增加了一些难度-您的列数未知。共有三种方法:

  1. 将其拆分,并以已知的最大列数返回您的集合
  2. 使用动态创建的语句并使用EXEC。但这不适用于VIEW或iTVF,也不适用于表格。
  3. 您将返回通用容器(例如XML),而不是列列表

具有已知的最大列数

第一个例子是

DECLARE @str VARCHAR(1000)='This,is,a,string,with,n,elements,...';

SELECT p.*
FROM
(
    SELECT A.[value]
          ,CONCAT('Column',A.[key]+1) AS ColumnName
    FROM OPENJSON('["' + REPLACE(@str,',','","') + '"]') A
) t
PIVOT
(
    MAX(t.[value]) FOR ColumnName IN(Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8,Column9 /*add as many as you need*/)
) p

提示:我用于拆分字符串的方法使用OPENJSON,在2016版之前不可用。但是您会发现很多其他方法。这只是一个示例,向您显示使用运行索引建立列名的PIVOT拆分器的组合。

未知列数

和具有动态创建的列列表的同一示例是:

DECLARE @str VARCHAR(1000)='This,is,a,string,with,n,elements,...';

DECLARE @CountElements INT=LEN(@str)-LEN(REPLACE(@str,',',''))+1;
DECLARE @columnList NVARCHAR(MAX)=
STUFF((
    SELECT TOP(@CountElements) 
           CONCAT(',Column',ROW_NUMBER() OVER(ORDER BY (SELECT 1))) 
    FROM master..spt_values /*has a lot of rows*/
    FOR XML PATH('')
),1,1,'');

DECLARE @Command NVARCHAR(MAX)=
N'SELECT p.*
FROM
(
    SELECT A.[value]
          ,CONCAT(''Column'',A.[key]+1) AS ColumnName
    FROM OPENJSON(''["'' + REPLACE(''' + @str + ''','','',''","'') + ''"]'') A
) t
PIVOT
(
    MAX(t.[value]) FOR ColumnName IN(' +  @columnList + ')
) p;';

EXEC(@Command);

提示:创建的语句与上面的语句完全相同。但是枢轴IN中的列列表是动态创建的。一般而言,这几乎可以处理几乎所有单词。

如果您需要更多帮助,请使用问题的编辑选项并提供更多详细信息。

用于表返回通用容器

的表的可内联方法

如果您需要针对表格使用此功能,则可以尝试以下操作:

DECLARE @tbl TABLE(ID INT IDENTITY,YourList NVARCHAR(MAX));
INSERT INTO @tbl VALUES('This,is,a,string,with,n,elements,...')
                      ,('And,one,more');

SELECT *
      ,CAST('<x>' + REPLACE((SELECT t.YourList AS [*] FOR XML PATH('')),',','</x><x>') + '</x>' AS XML) AS Splitted
FROM @tbl t

这将以XML之类的形式返回您的列表

<x>This</x>
<x>is</x>
<x>a</x>
<x>string</x>
<x>with</x>
<x>n</x>
<x>elements</x>
<x>...</x>

您可以根据需要获取每个元素的索引(如需要)

TheXml.value('/x[1]','nvarchar(max)') AS Element1

答案 1 :(得分:1)

DECLARE @string VARCHAR(MAX);
SET @string = 'hi,is,1,question,thanks,.,.,n';

DECLARE @SQL VARCHAR(MAX);
SET @SQL = 'SELECT ''' + REPLACE(@string, ',', ''',''') + '''';

EXEC (@SQL);

结果: enter image description here

  1. 在字符串的开头添加 SELECT',在字符串的末尾添加'

  2. 将所有替换为字符串中的','

  3. 因此字符串'hi,is,1,question,thanks,。,。,n'被替换为' SELECT'hi','is','1 ','问题','谢谢','。','。','n''

enter image description here

  1. 作为SQL查询执行

PS:如果要在列上使用它,则必须将其与CURSOR

结合使用

更新

    DECLARE @table TABLE
(
    ID INT IDENTITY,
    string VARCHAR(MAX)
);
INSERT INTO @table
VALUES
('This,is,a,string,,n,elements,..');
INSERT INTO @table
VALUES
('And,one,more');
INSERT INTO @table
VALUES
('Ugly,but,works,,,Yay!,..,,,10,11,12,13,14,15,16,17,18,19,..');

SELECT * FROM @table 

DECLARE @string_to_split VARCHAR(MAX);
DECLARE @sql_query_to_execute VARCHAR(MAX);
DECLARE @max_elements INT, @id INT, @i INT;

SET @i = 1;

DECLARE string_cursor CURSOR FOR SELECT ID, string FROM @table;

SELECT @max_elements = MAX(LEN(string) - LEN(REPLACE(string, ',', ''))) + 1 -- Find  max  number of elements */
FROM @table;

IF OBJECT_ID('tempdb..##my_temp_table_for_splitted_columns') <> 0 -- Create new temp table with valid amount of columns  
    DROP TABLE ##my_temp_table_for_splited_columns;

SET @sql_query_to_execute = 'create table ##my_temp_table_for_splitted_columns ( ID int,';  
WHILE @i <= @max_elements
BEGIN
    SET @sql_query_to_execute = @sql_query_to_execute + ' Col' + CAST(@i AS VARCHAR(max)) + ' varchar(25), ';
    SET @i = @i + 1;
END;

SELECT @sql_query_to_execute = SUBSTRING(@sql_query_to_execute, 1, LEN(@sql_query_to_execute) - 1) + ')';
EXEC (@sql_query_to_execute);

/* Split string for each row */
OPEN string_cursor;
FETCH NEXT FROM string_cursor
INTO @id,
     @string_to_split

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @i = MAX(LEN(@string_to_split) - LEN(REPLACE(@string_to_split, ',', ''))) + 1; -- check amount of columns for current string

    WHILE @i < @max_elements 
    BEGIN
        SET @string_to_split = @string_to_split + ','; -- add missing columns
        SET @i = @i + 1;
    END;

    SET @sql_query_to_execute = 'SELECT ' + CAST(@id AS VARCHAR(MAX)) + ',''' + REPLACE(@string_to_split, ',', ''',''') + '''';

    INSERT INTO ##my_temp_table_for_splitted_columns --insert result to temp table
    EXEC (@sql_query_to_execute);

    FETCH NEXT FROM string_cursor
    INTO @id,
         @string_to_split;
END;

CLOSE string_cursor;
DEALLOCATE string_cursor;

SELECT *
FROM ##my_temp_table_for_splitted_columns;

enter image description here