我是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
答案 0 :(得分: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>'),'&','&') + '</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)
答案 1 :(得分: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