我想以表格格式显示字符串,如下所示:
对于像'hi,is,1,question,thanks,.,.,n'
我需要这个结果:
column1 column2 column3 column4 ..... column
hi is 1 question ..... n
答案 0 :(得分:1)
这不是小事。您会发现很多示例,如何将字符串拆分为一组片段。您会发现很多示例,这些示例如何将行集转换为单行。但是-增加了一些难度-您的列数未知。共有三种方法:
EXEC
。但这不适用于VIEW或iTVF,也不适用于表格。第一个例子是
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);
在字符串的开头添加 SELECT',在字符串的末尾添加'
将所有,替换为字符串中的','
因此字符串'hi,is,1,question,thanks,。,。,n'被替换为' SELECT'hi','is','1 ','问题','谢谢','。','。','n''
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;