我正在使用SQL Server 2012,因此没有可用的字符串拆分功能。
考虑到我有一个名为DISK_VOLUME
的表,该表只有一列RESULT
,目前有4行:
RESULT
----------------------------------------
P: 220825387008 959589646336 DADOS
I: 166207356928 959589646336 INDEXS
E: 636080054272 799165902848 LOG
C: 462246113280 999651536896
我想要的是一个查询,该查询将这些行按空格分隔,显示4列,例如:
Caption | Space 1 | Space 2 | Volume Name
---------+--------------+----------------+--------------
P: | 220825387008 | 959589646336 | DADOS
I: | 166207356928 | 959589646336 | INDEXS
E: | 636080054272 | 799165902848 | LOG
C: | 462246113280 | 999651536896 |
但是无法控制字符串中的空格数量。它可以像
这意味着单独使用charindex(' ', ini_pos, ini_pos + 1)
是行不通的,因为我不能依靠空格查找后的下一个单词。
因此,基本上我正在寻找的是动态地将行按行分隔的任何函数或命令组合(递归函数,xml,IDK)。我所有的尝试都失败了。
答案 0 :(得分:1)
您可以尝试创建fn_split
函数。
CREATE FUNCTION fn_split
( @Words nvarchar(MAX)
, @splitStr varchar(50)
)
RETURNS @Result_Table TABLE
(
[word] nvarchar(max) NULL
)
BEGIN
Declare @TempStr nvarchar(MAX)
WHILE (CHARINDEX(@splitStr,@Words)>0)
BEGIN
Set @TempStr=SUBSTRING(@Words,1,CHARINDEX(@splitStr,@Words)-1)
Insert into @Result_Table (word) Values (@TempStr)
Set @Words = REPLACE(@Words,@TempStr+@splitStr,'')
END/*End While*/
IF(LEN(RTRIM(LTRIM(@Words)))>0 And CHARINDEX(@splitStr,RTRIM(LTRIM(@Words)))=0)
Begin
Set @TempStr=@Words
Insert into @Result_Table (word) Values (@TempStr)
End
RETURN
END
然后使用一点技巧将DISK_VOLUME
上的多个空格换成一个空格,替换三遍。
下一步使用row_number
窗口函数获取条件汇总函数的编号。
;WITH CTE as(
SELECT val,word,ROW_NUMBER() OVER(PARTITION BY val order by val) rn
FROM (
SELECT replace(replace(replace(DISK_VOLUME,' ','*&'),'&*',''),'*&',' ') val
FROM T
) t1 CROSS APPLY fn_split(t1.val,' ') v
)
SELECT max(CASE WHEN rn = 1 THEN word END) 'Caption',
max(CASE WHEN rn = 2 THEN word END) 'Space1',
max(CASE WHEN rn = 3 THEN word END) 'Space 2',
max(CASE WHEN rn = 4 THEN word END) 'Volume Name '
FROM CTE
GROUP BY val
答案 1 :(得分:1)
您可以使用XML
分割字符串。您首先需要将字符串转换为XML
,并用start
和end
XML
tags
替换空格。
将字符串转换为XML
后,您可以使用XQuery
以正确的格式获取结果。
要在多列中显示数据,您只需使用PIVOT
;WITH CTE AS
(
SELECT
F1.results,
O.splitdata,
row_number() over(partition by results order by (select 1)) rn FROM
(
SELECT *,
cast('<X>'+replace(F.results,' ','</X><X>')+'</X>' as XML) as xmlfilter
from [YourTableName] F
)F1
CROSS APPLY
(
SELECT fdata.D.value('.','varchar(500)') as splitdata
FROM f1.xmlfilter.nodes('X') as fdata(D)
) O
where splitdata <> ''
)
select [1] [Caption],[2] [Space1],[3] [Space2], [4] [Volume Name]
from CTE c
PIVOT (max(splitdata) for rn in ([1],[2],[3],[4])) pvt
输出
+---------+--------------+--------------+-------------+
| Caption | Space1 | Space2 | Volume Name |
+---------+--------------+--------------+-------------+
| C: | 462246113280 | 999651536896 | NULL |
+---------+--------------+--------------+-------------+
| E: | 636080054272 | 799165902848 | LOG |
+---------+--------------+--------------+-------------+
| I: | 166207356928 | 959589646336 | INDEXS |
+---------+--------------+--------------+-------------+
| P: | 220825387008 | 959589646336 | DADOS |
+---------+--------------+--------------+-------------+